14 KiB
name, description, argument-hint
| name | description | argument-hint |
|---|---|---|
| code-sync | 透過 `GITEA_TOKEN` 取得使用者有讀取權限的所有 Gitea 專案,依擁有者(owner)分組後列出讓使用者多選,再把選定擁有者底下有讀取權限的專案,於目標目錄(預設家目錄)依擁有者建立資料夾並逐一 clone;若專案已存在,則切換到 develop(再退而 master)並更新到最新。當使用者說同步 Gitea 專案、批次 clone、把某些擁有者的 repo 全抓下來、依擁有者分類 clone、批次更新本機專案到最新時觸發。不適用於:建立/刪除遠端 repo、單一專案的 clone(直接用 git 即可)、非 Gitea 的來源,或需要 push/改動遠端的操作。 | [--target-dir <根目錄>] [--owner <擁有者,以逗號分隔>] [--host <gitea 主機>] [--include-forks] [--ssh] [--yes] |
code-sync — 依擁有者批次 clone/更新 Gitea 專案
五階段 skill:先做前置設定(解析 token、gitea 主機、目標根目錄),再取得使用者有讀取權限的所有專案並依擁有者分組,接著列出所有擁有者讓使用者多選,然後列出選定擁有者底下有讀取權限的專案,最後在目標根目錄依擁有者建立資料夾並逐一 clone;專案已存在時改為切換到 develop(再退而 master)並更新到最新。
| 階段 | 動作 |
|---|---|
| A. 前置設定 | 確認 GITEA_TOKEN → 決定 gitea 主機(--host/$GITEA_HOST/目前 repo 的 origin/詢問)→ 決定目標根目錄(--target-dir,預設家目錄) |
| B. 取得可讀專案 | 以 token 呼叫 Gitea API 分頁取回使用者有讀取(pull)權限的所有專案 → 依 owner.login 分組 |
| C. 選擇擁有者 | 列出所有擁有者(含各自專案數)→ 讓使用者多選(--owner 已指定則沿用,不再詢問) |
| D. 列出選定專案 | 列出選定擁有者底下所有有讀取權限的專案(含是否已存在於本機) |
| E. Clone/更新 | 依擁有者建立資料夾 → 不存在則 clone;已存在則 fetch → 切到 develop(再退而 master)→ pull 更新到最新 |
輸出規範(務必遵守)
- 語言:所有面向使用者的輸出(擁有者清單、專案清單、進度、總結、反問)一律使用繁體中文(台灣用語);僅識別字、檔名、git/curl 指令、API 路徑等技術標識保留原文,不可使用簡體字。
- 編碼無亂碼:凡輸出含繁體中文、全形標點、emoji,一律 UTF-8(不含 BOM),不得出現問號方框或錯碼。
- Token 機密保護(極重要):gitea token 一律從環境變數讀取(如
$GITEA_TOKEN),絕不寫死在 skill、log 或任何輸出;不可 echo 含 token 的指令或 URL。所有顯示給使用者的指令/錯誤訊息都要遮蔽 token(如以***取代)。clone 時帶 token 的 URL 用變數帶入、不可印出,且 clone 完成後要把 origin 還原成不含 token 的乾淨 URL(見 E3),避免 token 落地在.git/config。 - 自動執行原則:除非使用者明確要求先確認,或遇到不可忽略的必要決策(例如缺 token、無法決定 gitea 主機、目標目錄不可寫、單一專案更新時工作區有未提交變更需使用者裁示),否則各階段只需輸出簡短計畫/進度後直接執行到完成。唯一一定會中斷的點是階段 C 的擁有者多選(除非已帶
--owner)。 - 不破壞既有工作:更新既有專案時若工作區有未提交變更而導致切換/pull 失敗,停止該專案的更新並回報,請使用者自行處理;絕不強制丟棄(不可
reset --hard/checkout -f/clean)。 - 唯讀本意:本 skill 只做 clone 與本機分支更新,不 push、不改遠端、不刪本機未追蹤檔。
參數
格式:[--target-dir <根目錄>] [--owner <擁有者,以逗號分隔>] [--host <gitea 主機>] [--include-forks] [--ssh] [--yes]
--target-dir <根目錄>:clone 的根目錄。省略時預設家目錄($HOME,Windows 為%USERPROFILE%)。實際每個專案會 clone 到<根目錄>/<擁有者>/<專案名>。--owner <擁有者,以逗號分隔>:預先指定要同步的擁有者(可多個,以逗號分隔,例如plugins,jeffery)。帶此參數時跳過階段 C 的多選詢問,直接同步這些擁有者;若指定的擁有者不在可讀清單內,回報並略過該擁有者。--host <gitea 主機>:gitea 主機(如gitea.jsc.idv.tw)。省略時依 A2 規則決定。--include-forks:一併納入 fork 來的專案;省略時預設排除 fork(fork=true的 repo 不列入)。--ssh:改用 SSH(ssh_url)clone,不帶 token;省略時預設用 HTTPS+token。--yes:全自動。即使未帶此參數,也依「自動執行原則」盡量不中斷;但階段 C 的擁有者多選仍會詢問(除非已帶--owner)。
階段 A:前置設定
A1. 確認 token
讀取環境變數 GITEA_TOKEN(或助理慣用的等價變數名)。
[ -n "${GITEA_TOKEN}" ] && echo "GITEA_TOKEN 已設定" || echo "GITEA_TOKEN 未設定"
- 未設定 → 回報「缺少
GITEA_TOKEN環境變數,無法存取 Gitea API」並停止;提示使用者於環境變數提供 token(不要請使用者把 token 貼進對話)。 - 不可 echo token 本身,只確認是否存在。
A2. 決定 gitea 主機
依序決定主機(取第一個成功者):
- 帶
--host <主機>→ 直接採用。 - 否則讀環境變數
$GITEA_HOST(若有)。 - 否則若目前工作目錄是 git repo 且
git remote get-url origin指向某 gitea 主機 → 取該 host。 - 以上皆無 → 詢問使用者 gitea 主機,不臆測。
主機僅取 host 部分(如 gitea.jsc.idv.tw),組 API base 為 https://<host>/api/v1。
A3. 決定目標根目錄
- 帶
--target-dir <根目錄>→ 採用(可含~,需展開為實際家目錄)。 - 省略 → 預設家目錄(
$HOME)。 - 確認根目錄存在且可寫;不存在時先建立(
mkdir -p)。若無法建立或不可寫,回報並停止。
輸出本次設定摘要(主機、根目錄、是否含 fork、HTTPS/SSH),再進入階段 B。
階段 B:取得使用者有讀取權限的所有專案並依擁有者分組
B1. 分頁取回可讀專案
以 token 呼叫 GET /api/v1/user/repos(回傳 token 對應使用者有權限存取的 repo:自有、組織成員、協作者),逐頁抓到取回筆數不足一頁為止(每頁上限以 API 為準,常見 limit=50):
# 不可印出含 token 的指令;token 以 Header 帶入,輸出時遮蔽
page=1
curl -sS \
-H "Authorization: token ${GITEA_TOKEN}" \
"https://<host>/api/v1/user/repos?page=${page}&limit=50"
- 持續累加
page直到某頁回傳筆數< limit(或回空陣列)為止,確保取得全部而非只第一頁。 - API 失敗(401/403/網路錯誤)→ 回報錯誤(遮蔽 token)並停止;401/403 多半是 token 失效或權限不足。
B2. 篩選與正規化
每筆 repo 取下列欄位:owner.login、name、full_name、clone_url、ssh_url、permissions.pull、fork、default_branch。
- 只保留
permissions.pull == true的專案(確有讀取權限)。 - 預設排除
fork == true;帶--include-forks才納入。 - 去除重複(以
full_name為鍵)。
B3. 依擁有者分組
以 owner.login 分組,統計每個擁有者底下的可讀專案數,並依擁有者名稱排序(專案數多者可優先列出)。無任何可讀專案 → 回報並結束。
階段 C:列出所有擁有者讓使用者多選
輸出一張「擁有者清單」表,含編號、擁有者、可讀專案數:
| # | 擁有者 | 可讀專案數 |
|---|
選擇方式:
- 帶
--owner參數 → 直接採用其中的擁有者,跳過詢問;清單中沒有的擁有者回報並略過。 - 未帶
--owner→ 這是不可忽略的必要決策,必須讓使用者多選:- 擁有者數量 ≤ 4 時,可用助理的多選提問元件(如 Claude Code 的多選問題)。
- 擁有者較多時,請使用者直接以編號或擁有者名稱回覆(支援多個,以逗號或空白分隔),並支援回覆
all/全部代表全選。 - 解析使用者回覆為擁有者集合;無法對應的輸入請回報並請使用者重選,不臆測。
選定後輸出「將同步的擁有者:…」再進入階段 D。
階段 D:列出選定擁有者底下有讀取權限的專案
對每個選定擁有者,列出其底下所有可讀專案,並標示本機是否已存在(<根目錄>/<擁有者>/<專案名>/.git 是否存在):
| 擁有者 | 專案 | 狀態 |
|---|---|---|
| 🆕 將 clone/♻️ 已存在將更新 |
輸出總計(將 clone N 個、將更新 M 個),除非使用者要求先確認,否則直接進入階段 E 執行。
階段 E:依擁有者建立資料夾並逐一 clone/更新
對選定擁有者底下的每個專案,依序處理(一次一個,互不干擾):
E1. 建立擁有者資料夾
mkdir -p "<根目錄>/<擁有者>"
專案目標路徑為 <根目錄>/<擁有者>/<專案名>。
E2. 專案不存在 → clone
-
HTTPS(預設):以 token 組 clone URL,用變數帶入、不可印出;clone 完成後還原乾淨 origin:
dest="<根目錄>/<擁有者>/<專案名>" # GITEA_TOKEN 來自環境變數;clone_url 形如 https://<host>/<owner>/<repo>.git git clone "https://oauth2:${GITEA_TOKEN}@<host>/<owner>/<repo>.git" "${dest}" # 還原成不含 token 的乾淨 URL,避免 token 落地在 .git/config git -C "${dest}" remote set-url origin "https://<host>/<owner>/<repo>.git" -
SSH(
--ssh):直接用ssh_url,不帶 token:git clone "<ssh_url>" "<根目錄>/<擁有者>/<專案名>" -
clone 後若遠端有
develop,將工作分支切到develop(沒有則維持default_branch/master);clone 失敗回報原因(遮蔽 token)並繼續下一個專案,不中斷整批。
E3. 專案已存在 → 切到 develop(再退而 master)並更新到最新
先盤點該專案狀態,有未提交變更則不強切:
dest="<根目錄>/<擁有者>/<專案名>"
git -C "${dest}" rev-parse --is-inside-work-tree # 確認是 git repo
git -C "${dest}" status --porcelain # 是否乾淨
git -C "${dest}" fetch --all --prune
-
目錄存在但不是 git repo(無
.git)→ 回報「目標已存在且非 git repo,略過」並繼續下一個;不刪除、不覆蓋。 -
工作區有未提交變更(
status --porcelain非空)→ 回報「有未提交變更,略過更新以免覆蓋」並繼續下一個;絕不強制丟棄。 -
工作區乾淨 → 依序選擇要更新的分支並切換、拉取:
if git -C "${dest}" rev-parse --verify --quiet origin/develop; then git -C "${dest}" switch develop 2>/dev/null || git -C "${dest}" switch -c develop --track origin/develop elif git -C "${dest}" rev-parse --verify --quiet origin/master; then git -C "${dest}" switch master 2>/dev/null || git -C "${dest}" switch -c master --track origin/master fi git -C "${dest}" pull --ff-onlyorigin/develop存在 → 切到develop;否則origin/master存在 → 切到master;兩者都不存在 → 回報「找不到 develop/master」並維持原分支、略過該專案。pull --ff-only無法快進(本地與遠端分歧)→ 回報該專案需人工處理(不自動 merge/rebase/reset),繼續下一個。- 已在目標分支時直接
pull --ff-only更新即可。
E4. 逐一處理、彙整結果
- 每個專案處理完記錄結果:🆕 已 clone/♻️ 已更新到最新/⏭️ 已略過(原因)/❌ 失敗(原因,遮蔽 token)。
- 單一專案失敗或略過不應中斷整批;全部處理完再輸出總結。
總結
各階段執行後輸出:
- 階段 A:使用的 gitea 主機、目標根目錄、是否含 fork、HTTPS/SSH。
- 階段 B/C:可讀專案總數、擁有者總數、使用者選定的擁有者。
- 階段 D/E:本批處理結果統計 —— 新 clone N 個、更新 M 個、略過 K 個(列原因)、失敗 J 個(列原因,遮蔽 token),並列出各專案的本機路徑。
- 若過程曾在指令中帶入 token,提醒確認輸出與 log 無明文 token。
呼叫方式
格式:[--target-dir <根目錄>] [--owner <擁有者,以逗號分隔>] [--host <gitea 主機>] [--include-forks] [--ssh] [--yes] —
全部可省略(根目錄預設家目錄;未帶 --owner 時於階段 C 詢問多選)。token 一律由環境變數(如 GITEA_TOKEN)提供,不寫死、不印出。
| 助理 | 呼叫 |
|---|---|
| Claude Code / Antigravity | /jsc:code-sync,或 /jsc:code-sync --owner plugins --target-dir ~/work、/jsc:code-sync --include-forks --ssh |
| Codex | $code-sync,或 $code-sync --owner plugins --target-dir ~/work,或用 /skills 選單 |
| OpenCode | 描述需求(如「用 GITEA_TOKEN 取得我有讀取權限的所有 Gitea 專案,依擁有者分組讓我多選,把選定擁有者的專案 clone 到家目錄;已存在的切到 develop/master 更新到最新」)自動觸發 |