Reviewed-on: #60 Reviewed-by: 系統管理員 <1+admin@noreply.localhost>
jsc-cli — CLI 偵測與技能庫部署
jsc 技能組的 CLI domain:找出已安裝的 AI CLI、列出各 CLI 可用模型並加上能力標籤,以及對每個 CLI 批次安裝、更新、解除安裝整組 jsc plugins。
安裝、更新、移除
Marketplace 統一為 jsc(https://gitea.jsc.idv.tw/plugins/meta.git),安裝 token 為 jsc-cli@jsc。每個指令一行:
| CLI | 安裝 | 更新 | 移除 |
|---|---|---|---|
| claude | claude plugin marketplace add https://gitea.jsc.idv.tw/plugins/meta.git && claude plugin install jsc-cli@jsc |
claude plugin marketplace update jsc && claude plugin update jsc-cli@jsc |
claude plugin uninstall jsc-cli@jsc |
| codex | codex plugin marketplace add https://gitea.jsc.idv.tw/plugins/meta.git && codex plugin add jsc-cli@jsc |
codex plugin marketplace upgrade jsc |
codex plugin remove jsc-cli@jsc |
| copilot | copilot plugin marketplace add https://gitea.jsc.idv.tw/plugins/meta.git && copilot plugin install jsc-cli@jsc |
copilot plugin marketplace update jsc && copilot plugin update jsc-cli@jsc |
copilot plugin uninstall jsc-cli@jsc |
| antigravity | git clone https://gitea.jsc.idv.tw/plugins/cli.git ~/plugins/cli && agy plugin install ~/plugins/cli |
git -C ~/plugins/cli pull && agy plugin uninstall jsc-cli && agy plugin install ~/plugins/cli |
agy plugin uninstall jsc-cli |
| kiro | kiro-cli plugin marketplace add https://gitea.jsc.idv.tw/plugins/meta.git && kiro-cli plugin install jsc-cli@jsc |
kiro-cli plugin marketplace update jsc && kiro-cli plugin update jsc-cli@jsc |
kiro-cli plugin uninstall jsc-cli@jsc |
antigravity 不支援 gitea URL 安裝,改用本地 clone 路徑。批次操作五個 CLI:使用
/jsc-cli:deploy。
舊入口
plugins/jsc已移除,marketplace 正本移到plugins/meta。marketplace 名稱仍是jsc(取自 marketplace.json 的name欄位,與存取庫名無關),安裝 token 不變;已從舊入口安裝過的人先執行claude plugin marketplace remove jsc,再依上表重新 add。
工具
| 工具 | 用途 |
|---|---|
tools/detect-clis.sh |
列出已安裝的 AI CLI 與執行檔路徑(TSV:name / path / version;antigravity 的執行檔為 agy、kiro 為 kiro-cli) |
tools/deploy.sh |
對單一 CLI 執行安裝、更新或解除安裝(deploy.sh [-n] {mode} {cli} {domain}...,mode 為 install / update / uninstall);印出每個指令與其結束碼,最後一行 result 標 ok 或 fail。-n 只印指令不執行。上表五個 CLI 的指令差異全部收在這支腳本裡。Codex 更新 jsc-cli 與 jsc-hooks 後會把舊版快取路徑補成指向新版的相容連結,避免正在跑的部署流程找不到 helper 腳本,也避免尚未重啟的工作階段在 Stop hook 階段找不到舊路徑。install 或 update 全數成功時,收尾轉呼叫 jsc-hooks 的 restart-gate.sh require 掛上重啟閘門,並印一行 restart 標出狀態檔位置;uninstall 不寫。尋找 restart-gate.sh 時優先用 $JSC_HOME/current/jsc-hooks、本地 clone 與 Kiro skills,最後才掃各 CLI 快取,避免部署收尾綁死單一 CLI 的版號路徑。狀態檔的路徑、格式與判讀全在 restart-gate.sh,這支腳本不自己拼——格式只留一個真實來源。站台取自 GITEA_HOST,本地 clone 目錄取自 JSC_LOCAL_PLUGINS,兩者的預設值見下表 |
tools/check-requires.sh |
check-requires.sh {cli} {manifest} 檢查 manifest 的 jsc.requires 最低版本。沒有宣告就通過;版本不符或缺相依 plugin 就回 status=blocked 與結束碼 1。deploy.sh update 在每個 domain 更新前呼叫它一次:結束碼 1 只印一行 warn,那個 domain 照樣更新——跳過會讓落後的 domain 永遠等不到相依版本,也就永遠更新不到,真正的阻擋由 jsc-hooks 的 version-guard.sh 在技能被叫用時執行;結束碼 2 以上是檢查腳本自己出錯,讀不到結論就不當成通過,印 skip 並跳過該 domain |
tools/write-guides.sh |
產生這台機器專屬的更新指引 $JSC_HOME/update-guide.md 與移除指引 $JSC_HOME/remove-guide.md(write-guides.sh [-n] {install|update} {domain}...),一輪部署跑一次。CLI 清單取自 detect-clis.sh,每支 CLI 的指令字面直接取自 deploy.sh -n 的輸出,所以指引寫的就是實際會跑的指令;kiro 走不走本地複製退路也依實際偵測結果標注 |
tools/list-models.sh |
讀各 CLI 設定檔列出模型(TSV:cli / model / in-use);設定檔缺失就不輸出該 CLI 的列,一律 exit 0。設定檔位置只寫在這支腳本裡 |
tools/model-config.sh |
解析 SDLC 各階段的偏好模型鏈(get {stage}、list、resolve {stage} 印出目前 CLI 可用的第一個模型);專案 .jsc/models 優先於 $JSC_HOME/models.conf,格式見 references/model-tags.md。鏈只影響建議與偏好順序,不影響閘門放行 |
tools/config-spec.tsv |
設定規格表:每個環境變數與設定檔一列,標明必要或選擇、預設值、驗證方式、修法。體檢與設定共用這一份,新增設定時要同步補一列 |
tools/scan-config.sh |
依規格表盤點設定現況(scan {global|project|all} 印 TSV 與 summary、spec 印規格表、orphans 找出漏登錄的變數);-o 為離線模式,需要連 Gitea 的檢查一律標 skipped。唯讀,不寫任何設定;帶 TOKEN 的項目只印 set 或 unset |
tools/apply-config.sh |
把設定寫進 shell rc 檔(set {KEY} {VALUE}、unset {KEY})或建立目錄(mkdir {PATH});show 印出目前設定,rcfiles 印出會寫入的檔案。內容一律收在 # jsc-config 標記段落之間,整段重寫不疊加,段落外不動。動檔案前先備份到 $JSC_HOME/backup/config/{yyyyMMdd_HHmmss}/,備份失敗就不寫;寫完重讀驗證。fish 自動改用 set -gx 語法 |
tools/model-tags.sh |
解析 references/model-tags.md 的能力標籤與 SDLC 階段必要標籤(dump、sync、stage {階段}、model {模型 id}、gate {階段} {模型 id});sync 寫出 $JSC_HOME/model-tags.tsv 供 jsc-hooks 的 sdlc-gate 讀取。gate 的結束碼 0 為 PASS、1 為缺標籤、2 為模型或階段不在表上,/jsc-cli:delegate 依這三碼決定收下或退回 |
tools/build-todo.sh |
把三支檢查腳本的輸出合併成一張「待修項目」表(--config 收 scan-config.sh scan、--wiring {cli}= 收 wire-cli.sh status、--version 收 version-guard.sh report);類別固定排成 missing、invalid、unwired、落後,一項都沒有時仍印一列「無」。/jsc-cli:doctor 與 /jsc-cli:setup 共用這一份合併規則,兩邊各寫一次就會各自漂移 |
Skills 目錄
呼叫方式:Claude / Antigravity /jsc-cli:{name};Codex ${name};Copilot / Kiro 描述需求自動觸發。
models
三支腳本併行取得資料:tools/detect-clis.sh 取已安裝 CLI、tools/list-models.sh 讀出各 CLI 可使用的模型、tools/model-config.sh list 取各階段的偏好模型鏈。接著依 references/model-tags.md 加上能力標籤,用 tools/model-tags.sh sync 把標籤表寫進 $JSC_HOME/model-tags.tsv 供 sdlc-gate 讀取,並列出 SDLC 各階段的必要標籤(plan、analyze 需 reasoning-max;implement 需 coding;maintain 任意)。jsc-sdlc 閘門一律以能力標籤判定,偏好鏈只用來建議切換目標。
delegate
把單一明確任務交給另一個已安裝的 AI agent CLI 當作 subagent 執行。CLI 清單一律取自 tools/detect-clis.sh,模型夠不夠格一律由 tools/model-tags.sh gate 的結束碼判定,不讓模型自評標籤。可指定目標 CLI,也可依任務需求用能力標籤篩選模型,或強制指定模型。每個目標分開派工,預設只讀,寫入範圍以路徑清單明列;回傳採固定的 TSV 契約(result、summary、criterion、wrote、error),供主 agent 逐項驗證。此技能不負責模型盤點或 plugin 部署。
deploy
技能庫批次安裝、更新、解除安裝:偵測 CLI、版本建議、marketplace domain 清單三者併行取得 → 秀出 jsc-hooks/hooks/version-guard.sh report 的版本證據表,再依 recommend 的一行結論(recommend<TAB>{update|none|unverifiable},只印這一行,不混印表格)標出推薦選項;輸出裡找不到 recommend 行就退回 report 自行推導並在回報寫明是降級路徑 → 決策樹選模式(呼叫方已確認過模式就沿用,不重問)→ 每個 CLI 一個 sub agent,全部同時啟動呼叫 tools/deploy.sh 執行原生 plugin 指令(統一 marketplace jsc,token jsc-{domain}@jsc)→ update 前逐一檢查 jsc.requires,版本不符只印 warn 並照樣更新該 domain、回報還缺哪一版,阻擋交給 version-guard.sh 在技能被叫用時執行;檢查腳本自己出錯才印 skip 跳過該 domain → Codex 更新 jsc-cli 與 jsc-hooks 時保留舊快取相容連結 → install、update 後把偵測到的 CLI 清單交給 jsc-hooks:hooks-install,取它的彙總結果,只自行加判一條「smoke 出現 No such file 一律視為更新失敗」。domain 名單動態取自 plugins/meta 的 marketplace.json,不硬編碼。
doctor
一次體檢執行環境,只讀不改。四項檢查同時啟動,各一個 sub agent:技能版本(jsc-hooks/hooks/version-guard.sh report)、Hook 接線(jsc-hooks/tools/wire-cli.sh status,唯讀子命令)、設定現況(tools/scan-config.sh scan all 比對 tools/config-spec.tsv,一次掃完全域與專案兩個範圍)、漏登錄變數(scan-config.sh orphans)。唯讀契約下放程式層:呼叫 wire-cli.sh 一律帶 JSC_READONLY=1,打錯子命令也不會改到機器。每項各出一張表,專案那張一定寫出掃的是哪個目錄;待修項目由 tools/build-todo.sh 合併三份輸出並排序。整份結果寫進 wiki CHECK_{HASH},HASH 取 {短主機名}/{登入帳號},兩個值都由程式取,主機名一律切掉網域,只保留最新一次。目錄頁 CHECK_CONTENTS 住另一個庫(JSC_WIKI_REPO_CONTENTS),版面是 H1 加 > 引言,再一台機器一個 H2 區塊,頁上沒有 markdown 表格;改由 jsc-gitea/tools/wiki-contents.sh upsert CHECK 1 CHECK_{HASH} 只寫本機那一個區塊,欄位是 - {欄位名}:{值} 的條列。鍵是 H2 標題,也就是體檢頁頁名 CHECK_{HASH},不是任何含網址的值:網址會隨站台、存取庫與頁名編碼改變,頁名只由主機加帳號決定,拿網址當鍵就比不中,同一台機器每體檢一次就多附一個區塊。第二個參數 1 是 <key-col>,只在頁面還是舊表格、需要自動轉檔時用得到,指舊表格裡持有 [CHECK_{HASH}](網址) 的第 1 欄。「體檢頁」那一條的連結給人點,填絕對網址。修復交給 /jsc-cli:setup,體檢本身不動任何設定。
setup
修復 /jsc-cli:doctor 找出的問題,一次一項,逐項確認才動手。待修清單優先讀 wiki CHECK_{HASH},沒有頁面就當場重掃:三支檢查腳本併行跑,再用 tools/build-todo.sh 合併成同一張表。依修法分流:auto 用 tools/apply-config.sh 直接寫、ask 先用決策樹問到值再寫、manual 印出步驟交給操作者。複合修復交回原主:版本落後找 /jsc-cli:deploy(連同已確認的模式與版本報告一起傳過去,不讓它重問重查)、hook 未接線找 /jsc-hooks:hooks-install、缺 model-tags.tsv 找 /jsc-cli:models。逐項確認維持循序,寫完的重驗併行;環境變數類只驗「rc 段落裡確實有那一行」,環境層面交給下一次 /jsc-cli:doctor。最後覆寫體檢頁 CHECK_{HASH},並用 jsc-gitea/tools/wiki-contents.sh upsert CHECK 1 CHECK_{HASH} 以 H2 標題(也就是體檢頁頁名)當鍵,更新目錄頁 CHECK_CONTENTS 的本機那一個區塊,兩頁分屬不同存取庫。
環境變數
| 變數 | 用途 | 未設定時 |
|---|---|---|
GITEA_HOST |
Gitea 站台(可省略 scheme,預設 https) | 用正本站台 https://gitea.jsc.idv.tw |
JSC_GITEA_OWNER |
技能組存取庫的 owner | 用 plugins |
JSC_LOCAL_PLUGINS |
antigravity 與 kiro 退路用的本地 clone 目錄 | 用 $JSC_HOME/plugins(即 ~/.jsc/plugins) |
JSC_KIRO_SKILLS |
kiro 退路複製 skills 的目標目錄 | 用 ~/.kiro/skills |
JSC_DEPLOY_DRYRUN |
設為 1 等同 deploy.sh -n,只印指令不執行 |
照常執行 |
JSC_WIKI_REPO_CHECK |
體檢內容頁 CHECK_{HASH} 所在的 {owner}/{repo};只管內容頁,管不到目錄頁 |
退回 JSC_WIKI_REPO;兩個都沒有就略過寫入,並把這一項列進待修 |
JSC_WIKI_REPO_CONTENTS |
目錄頁 CHECK_CONTENTS 所在的 {owner}/{repo}。目錄頁與內容頁分屬不同存取庫:所有 {TYPE}_CONTENTS 一律住這一個庫,內容頁才看各自的型別變數 |
退回 JSC_WIKI_REPO;兩個都沒有就略過目錄頁寫入,並把這一項列進待修。不退回 JSC_WIKI_REPO_CHECK |
JSC_CONFIG_SPEC |
改讀別份設定規格表(測試 scan-config.sh 時用) |
用 tools/config-spec.tsv |
JSC_HOME |
hook 資料目錄,兩份指引與重啟狀態檔都寫在這裡 | 用 ~/.jsc |
JSC_RESTART_GATE |
設成 off 可略過部署後的重啟提示閘門(判讀在 jsc-hooks,jsc-cli 只負責寫狀態檔) |
照常提示重啟 |
JSC_LOCAL_PLUGINS 的預設值刻意避開 ~/plugins:那是維護者放技能組開發 checkout 的地方,git pull 下去會蓋掉未提交的工作。這個變數指到的目錄若是開發中的樹(有未提交變更,或有未推送的 commit),deploy.sh 只印一行 skip 並直接用現地內容安裝,不執行 git pull。
部署留在機器上的檔案
| 檔案 | 何時產生 | 用途 |
|---|---|---|
$JSC_HOME/update-guide.md |
install、update 收尾 | 下次更新的依據:偵測到的 CLI、每支的安裝方式與實際指令、marketplace token、domain 清單 |
$JSC_HOME/remove-guide.md |
install、update 收尾 | 整組移除的依據:各 CLI 的移除指令,加上 $JSC_HOME、本地 clone、kiro 技能目錄、rc 檔 # jsc-config 段落這些殘留物 |
$JSC_HOME/restart-required.d/{cli} |
install、update 全數成功時 | 一支 CLI 一份,內容是四行 key=value(at、mode、domains、cli)。jsc-hooks 只讀當前 CLI 那一份來提示重啟,別支的不影響這一支;逃生門 JSC_RESTART_GATE=off 也在那邊判讀。路徑與格式的唯一來源是 jsc-hooks/hooks/restart-gate.sh,deploy.sh 只轉呼叫它的 require |
兩份指引一律整份覆寫,內容依產生當下的偵測結果生成,不寫死。uninstall 不產生指引、也不寫重啟狀態檔。