Files
cli/tools/list-models.sh
jiantw83 8112905364 docs(cli): 把結束碼約定寫進腳本檔頭,README 跟著對齊
detect-clis.sh 與 list-models.sh 一律回零:找不到執行檔,或讀不到設定檔,
都只是少掉那一列,不算失敗。這個約定過去只存在讀過腳本的人腦袋裡。
呼叫端很容易拿結束碼去判斷「這台機器有沒有裝 CLI」,然後永遠判斷錯。
現在把它寫在檔頭,兩支腳本的行為都不動。

README 的腳本表與技能說明同步更新,讀 README 的人看到的流程,才跟技能
裡實際寫的一致。
2026-08-31 11:09:59 +08:00

87 lines
3.6 KiB
Bash
Executable File
Raw Permalink 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.
#!/usr/bin/env sh
# list-models.sh — 讀各 AI CLI 的設定檔,列出模型與目前使用中的模型。
# 輸出(TSV,一行一個模型):cli<TAB>model<TAB>in-use(in-use 為 yes 或 no)
# 設定檔不存在或裡面沒寫模型,就不輸出該 CLI 的列;一律 exit 0。
# 設定檔位置只寫在這裡,SKILL.md 不再抄一份:
# claude ${CLAUDE_CONFIG_DIR:-~/.claude}/settings.json 的 model;ANTHROPIC_MODEL 可覆寫使用中的模型
# codex ${CODEX_HOME:-~/.codex}/config.toml:頂層 model 為使用中,[profiles.*] 的 model 併入清單
# copilot ~/.copilot/settings.json,退回 ~/.config/copilot/settings.json
# antigravity ~/.antigravity/settings.json,退回 ~/.config/antigravity/settings.json
# kiro ~/.kiro/settings/cli.json,退回 ~/.config/kiro/settings.json
# 五個 CLI 都沒有「列出可用模型」的指令,所以清單只到設定檔寫出來的模型。
# 沒有列的 CLI 由 skills/models 的 sub agent 補上預設模型並標註「預設推定」。
# 結束碼: 0=一律回 0。設定檔不存在、讀不到或裡面沒寫模型,都只是少掉那個 CLI 的列,
# 不算失敗,所以沒有其他碼。呼叫端要看輸出有沒有該 CLI 的列,
# 不要拿結束碼判斷讀不讀得到設定檔。
set -u
# 取第一個存在的檔案;都不存在就不印。
first_file() { # $@=候選路徑
for f in "$@"; do
[ -f "$f" ] && { printf '%s\n' "$f"; return 0; }
done
return 0
}
# 取 JSON 檔裡某個鍵的所有字串值,一行一個,順序照檔案。
json_val() { # $1=檔案 $2=鍵名
[ -n "$1" ] || return 0
[ -f "$1" ] || return 0
grep -oE "\"$2\"[[:space:]]*:[[:space:]]*\"[^\"]+\"" "$1" 2>/dev/null \
| sed -e 's/^[^:]*:[[:space:]]*"//' -e 's/"$//'
return 0
}
# 取 TOML 檔裡所有 model 設定值,一行一個,順序照檔案。
# 只認行首的 model=,所以 model_reasoning_effort 這類鍵不會誤中。
toml_val() { # $1=檔案
[ -n "$1" ] || return 0
[ -f "$1" ] || return 0
grep -E '^[[:space:]]*model[[:space:]]*=' "$1" 2>/dev/null \
| sed -e 's/^[^=]*=[[:space:]]*//' -e 's/[[:space:]]*#.*$//' \
-e 's/^"//' -e 's/"[[:space:]]*$//' -e "s/^'//" -e "s/'[[:space:]]*$//"
return 0
}
# 印出某 CLI 的列:使用中的模型排第一,重複的只留一筆。
emit() { # $1=cli $2=使用中的模型(可空) $3=模型清單(換行分隔,可空)
printf '%s\n%s\n' "$2" "$3" | awk -v cli="$1" -v cur="$2" '
{ gsub(/^[ \t]+|[ \t]+$/, "") }
$0 == "" { next }
seen[$0]++ { next }
{ printf "%s\t%s\t%s\n", cli, $0, ($0 == cur ? "yes" : "no") }'
}
# claude
cfg=$(first_file "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json")
list=$(json_val "$cfg" model)
cur="${ANTHROPIC_MODEL:-}"
[ -n "$cur" ] || cur=$(printf '%s\n' "$list" | head -n1)
emit claude "$cur" "$list"
# codex
cfg=$(first_file "${CODEX_HOME:-$HOME/.codex}/config.toml")
list=$(toml_val "$cfg")
cur=$(printf '%s\n' "$list" | head -n1)
emit codex "$cur" "$list"
# copilot
cfg=$(first_file "$HOME/.copilot/settings.json" "$HOME/.config/copilot/settings.json")
list=$(json_val "$cfg" model)
cur=$(printf '%s\n' "$list" | head -n1)
emit copilot "$cur" "$list"
# antigravity
cfg=$(first_file "$HOME/.antigravity/settings.json" "$HOME/.config/antigravity/settings.json")
list=$(json_val "$cfg" model)
cur=$(printf '%s\n' "$list" | head -n1)
emit antigravity "$cur" "$list"
# kiro
cfg=$(first_file "$HOME/.kiro/settings/cli.json" "$HOME/.config/kiro/settings.json")
list=$(json_val "$cfg" model)
cur=$(printf '%s\n' "$list" | head -n1)
emit kiro "$cur" "$list"
exit 0