AI编程(4) : claude code linux api厂商管理
必需依赖:1. bash - 脚本解释器(#!/bin/bash)2. python3 - 用于 JSON 数据处理(脚本第 447-451 行会检查)Python 模块(标准库,无需额外安装):- json - JSON 解析和生成- sys - 系统功能配置文件:- ~/.claude/settings.json - 必须存在(第 453-457 行检查)- ~/.claude_provide
·
1.效果图

2.依赖
必需依赖:
1. bash - 脚本解释器(#!/bin/bash)
2. python3 - 用于 JSON 数据处理(脚本第 447-451 行会检查)
Python 模块(标准库,无需额外安装):
- json - JSON 解析和生成
- sys - 系统功能
配置文件:
- ~/.claude/settings.json - 必须存在(第 453-457 行检查)
- ~/.claude_providers.json - 自动创建(如果不存在)
总结: 除了 python3,只需要 bash(Linux/macOS 默认自带)和 Python 标准库。没有第三方依赖。
3.配置别名
cat >> ~/.bashrc <<'EOF'
# claude code
alias cpm='~/claude-provider-manager.sh'
EOF
source ~/.bashrc
4.代码(claude-provider-manager.sh)
vi ~/claude-provider-manager.sh
#!/bin/bash
# Claude Code 厂商管理工具
# 管理 ~/.claude/settings.json 中的 API 配置
SETTINGS_FILE="$HOME/.claude/settings.json"
PROVIDERS_FILE="$HOME/.claude_providers.json"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
BOLD='\033[1m'
# Python JSON 处理函数
py_json() {
python3 -c "
import json, sys
data = json.load(sys.stdin)
$1
" 2>/dev/null
}
# 初始化厂商配置文件
init_providers_file() {
if [[ ! -f "$PROVIDERS_FILE" ]]; then
echo '{"providers":[],"active":""}' > "$PROVIDERS_FILE"
fi
}
# 获取当前启用的厂商名称
get_active_provider() {
python3 -c "
import json
with open('$PROVIDERS_FILE') as f:
data = json.load(f)
print(data.get('active', ''))
" 2>/dev/null
}
# 获取厂商数量
get_provider_count() {
python3 -c "
import json
with open('$PROVIDERS_FILE') as f:
data = json.load(f)
print(len(data.get('providers', [])))
" 2>/dev/null
}
# 获取厂商列表 (每行一个 JSON)
get_providers() {
python3 -c "
import json
with open('$PROVIDERS_FILE') as f:
data = json.load(f)
for p in data.get('providers', []):
print(json.dumps(p, ensure_ascii=False))
" 2>/dev/null
}
# 获取厂商信息 by index
get_provider_by_index() {
local idx=$1
python3 -c "
import json
with open('$PROVIDERS_FILE') as f:
data = json.load(f)
providers = data.get('providers', [])
if $idx < len(providers):
print(json.dumps(providers[$idx], ensure_ascii=False))
" 2>/dev/null
}
# 获取厂商信息 by name
get_provider_by_name() {
local name="$1"
python3 -c "
import json
with open('$PROVIDERS_FILE') as f:
data = json.load(f)
for p in data.get('providers', []):
if p.get('name') == '$name':
print(json.dumps(p, ensure_ascii=False))
break
" 2>/dev/null
}
# 检查厂商名是否存在
provider_exists() {
local name="$1"
python3 -c "
import json
with open('$PROVIDERS_FILE') as f:
data = json.load(f)
for p in data.get('providers', []):
if p.get('name') == '$name':
sys.exit(0)
sys.exit(1)
" 2>/dev/null
}
# 添加厂商
add_provider() {
local name="$1"
local base_url="$2"
local token="$3"
local model="$4"
python3 -c "
import json
with open('$PROVIDERS_FILE', 'r') as f:
data = json.load(f)
data['providers'].append({
'name': '$name',
'base_url': '$base_url',
'token': '$token',
'model': '$model'
})
with open('$PROVIDERS_FILE', 'w') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
"
}
# 更新厂商
update_provider() {
local idx=$1
local name="$2"
local base_url="$3"
local token="$4"
local model="$5"
python3 -c "
import json
with open('$PROVIDERS_FILE', 'r') as f:
data = json.load(f)
data['providers'][$idx] = {
'name': '$name',
'base_url': '$base_url',
'token': '$token',
'model': '$model'
}
with open('$PROVIDERS_FILE', 'w') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
"
}
# 删除厂商
delete_provider() {
local idx=$1
python3 -c "
import json
with open('$PROVIDERS_FILE', 'r') as f:
data = json.load(f)
del data['providers'][$idx]
with open('$PROVIDERS_FILE', 'w') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
"
}
# 设置活跃厂商
set_active_provider() {
local name="$1"
python3 -c "
import json
with open('$PROVIDERS_FILE', 'r') as f:
data = json.load(f)
data['active'] = '$name'
with open('$PROVIDERS_FILE', 'w') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
"
}
# 初始化 settings.json(如果不存在或为空)
init_settings_file() {
if [[ ! -f "$SETTINGS_FILE" ]] || [[ ! -s "$SETTINGS_FILE" ]]; then
mkdir -p "$(dirname "$SETTINGS_FILE")"
echo '{}' > "$SETTINGS_FILE"
fi
}
# 更新 settings.json
update_settings() {
local base_url="$1"
local token="$2"
local model="$3"
# 确保文件存在且有效
init_settings_file
# 备份原文件
cp "$SETTINGS_FILE" "${SETTINGS_FILE}.bak"
python3 -c "
import json
try:
with open('$SETTINGS_FILE', 'r') as f:
content = f.read().strip()
data = json.loads(content) if content else {}
except (json.JSONDecodeError, FileNotFoundError):
data = {}
if 'env' not in data:
data['env'] = {}
data['env']['ANTHROPIC_BASE_URL'] = '$base_url'
data['env']['ANTHROPIC_AUTH_TOKEN'] = '$token'
data['env']['ANTHROPIC_MODEL'] = '$model'
data['env']['ANTHROPIC_DEFAULT_OPUS_MODEL'] = '$model'
data['env']['ANTHROPIC_DEFAULT_SONNET_MODEL'] = '$model'
data['env']['ANTHROPIC_DEFAULT_HAIKU_MODEL'] = '$model'
data['env']['ANTHROPIC_REASONING_MODEL'] = '$model'
with open('$SETTINGS_FILE', 'w') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
"
}
# 显示主菜单
show_menu() {
clear
echo -e "${BOLD}${CYAN}========================================${NC}"
echo -e "${BOLD}${CYAN} Claude Code 厂商管理工具${NC}"
echo -e "${BOLD}${CYAN}========================================${NC}"
local active=$(get_active_provider)
if [[ -n "$active" ]]; then
local active_info=$(get_provider_by_name "$active")
if [[ -n "$active_info" ]]; then
local active_model=$(echo "$active_info" | python3 -c "import json,sys; print(json.load(sys.stdin).get('model',''))")
echo -e "\n${GREEN}当前启用: ${BOLD}$active${NC} ${YELLOW}($active_model)${NC}"
fi
else
echo -e "\n${YELLOW}当前未启用任何厂商${NC}"
fi
echo -e "\n${BOLD}厂商列表:${NC}"
local count=$(get_provider_count)
if [[ "$count" -eq 0 ]]; then
echo -e " ${YELLOW}(暂无厂商,请添加)${NC}"
else
local idx=0
while IFS= read -r provider; do
[[ -z "$provider" ]] && continue
local name=$(echo "$provider" | python3 -c "import json,sys; print(json.load(sys.stdin).get('name',''))")
local model=$(echo "$provider" | python3 -c "import json,sys; print(json.load(sys.stdin).get('model',''))")
if [[ "$name" == "$active" ]]; then
echo -e " ${GREEN}${BOLD}$((idx+1)). [✓] $name${NC} ${YELLOW}$model${NC}"
else
echo -e " $((idx+1)). [ ] $name ${CYAN}$model${NC}"
fi
((idx++))
done < <(get_providers)
fi
echo -e "\n${BOLD}操作:${NC}"
echo " a. 添加厂商"
echo " e. 编辑厂商"
echo " d. 删除厂商"
echo " q. 退出"
echo ""
}
# 添加厂商对话框
add_provider_dialog() {
echo -e "\n${BOLD}--- 添加厂商 ---${NC}"
read -p "厂商名称: " name
[[ -z "$name" ]] && echo -e "${RED}名称不能为空${NC}" && return
if provider_exists "$name"; then
echo -e "${RED}厂商已存在: $name${NC}"
return
fi
read -p "Base URL: " base_url
[[ -z "$base_url" ]] && echo -e "${RED}Base URL 不能为空${NC}" && return
read -p "Token: " token
[[ -z "$token" ]] && echo -e "${RED}Token 不能为空${NC}" && return
read -p "Model: " model
[[ -z "$model" ]] && echo -e "${RED}Model 不能为空${NC}" && return
add_provider "$name" "$base_url" "$token" "$model"
echo -e "${GREEN}厂商添加成功: $name${NC}"
read -p "是否立即启用? (y/n): " enable
if [[ "$enable" == "y" || "$enable" == "Y" ]]; then
enable_provider_by_name "$name"
fi
}
# 编辑厂商对话框
edit_provider_dialog() {
local count=$(get_provider_count)
if [[ "$count" -eq 0 ]]; then
echo -e "${RED}暂无厂商可编辑${NC}"
read -p "按回车继续..."
return
fi
echo -e "\n${BOLD}--- 编辑厂商 ---${NC}"
echo "选择要编辑的厂商:"
local idx=0
local names=()
while IFS= read -r provider; do
[[ -z "$provider" ]] && continue
local name=$(echo "$provider" | python3 -c "import json,sys; print(json.load(sys.stdin).get('name',''))")
echo " $((idx+1)). $name"
names+=("$name")
((idx++))
done < <(get_providers)
read -p "请选择 (1-$count): " choice
if [[ ! "$choice" =~ ^[0-9]+$ ]] || [[ "$choice" -lt 1 ]] || [[ "$choice" -gt "$count" ]]; then
echo -e "${RED}无效选择${NC}"
read -p "按回车继续..."
return
fi
local sel_idx=$((choice-1))
local provider=$(get_provider_by_index $sel_idx)
local old_name=$(echo "$provider" | python3 -c "import json,sys; print(json.load(sys.stdin).get('name',''))")
local old_base_url=$(echo "$provider" | python3 -c "import json,sys; print(json.load(sys.stdin).get('base_url',''))")
local old_token=$(echo "$provider" | python3 -c "import json,sys; print(json.load(sys.stdin).get('token',''))")
local old_model=$(echo "$provider" | python3 -c "import json,sys; print(json.load(sys.stdin).get('model',''))")
echo -e "\n编辑厂商: ${BOLD}$old_name${NC} (回车保留原值)"
read -p "厂商名称 [$old_name]: " name
name="${name:-$old_name}"
read -p "Base URL [$old_base_url]: " base_url
base_url="${base_url:-$old_base_url}"
read -p "Token [$old_token]: " token
token="${token:-$old_token}"
read -p "Model [$old_model]: " model
model="${model:-$old_model}"
update_provider $sel_idx "$name" "$base_url" "$token" "$model"
# 如果修改的是当前启用的厂商,更新 settings.json
local active=$(get_active_provider)
if [[ "$old_name" == "$active" ]]; then
set_active_provider "$name"
update_settings "$base_url" "$token" "$model"
echo -e "${GREEN}厂商已更新并重新启用: $name${NC}"
else
echo -e "${GREEN}厂商已更新: $name${NC}"
fi
read -p "按回车继续..."
}
# 删除厂商对话框
delete_provider_dialog() {
local count=$(get_provider_count)
if [[ "$count" -eq 0 ]]; then
echo -e "${RED}暂无厂商可删除${NC}"
read -p "按回车继续..."
return
fi
echo -e "\n${BOLD}--- 删除厂商 ---${NC}"
echo "选择要删除的厂商:"
local idx=0
local names=()
while IFS= read -r provider; do
[[ -z "$provider" ]] && continue
local name=$(echo "$provider" | python3 -c "import json,sys; print(json.load(sys.stdin).get('name',''))")
echo " $((idx+1)). $name"
names+=("$name")
((idx++))
done < <(get_providers)
read -p "请选择 (1-$count): " choice
if [[ ! "$choice" =~ ^[0-9]+$ ]] || [[ "$choice" -lt 1 ]] || [[ "$choice" -gt "$count" ]]; then
echo -e "${RED}无效选择${NC}"
read -p "按回车继续..."
return
fi
local sel_idx=$((choice-1))
local del_name="${names[$sel_idx]}"
local active=$(get_active_provider)
if [[ "$del_name" == "$active" ]]; then
echo -e "${YELLOW}警告: 该厂商当前已启用,删除后将无法使用${NC}"
fi
read -p "确认删除 '$del_name'? (y/n): " confirm
if [[ "$confirm" == "y" || "$confirm" == "Y" ]]; then
delete_provider $sel_idx
if [[ "$del_name" == "$active" ]]; then
set_active_provider ""
fi
echo -e "${GREEN}厂商已删除: $del_name${NC}"
else
echo "已取消"
fi
read -p "按回车继续..."
}
# 启用厂商
enable_provider_by_index() {
local idx=$1
local provider=$(get_provider_by_index $idx)
if [[ -z "$provider" ]]; then
echo -e "${RED}无效的厂商索引${NC}"
return 1
fi
local name=$(echo "$provider" | python3 -c "import json,sys; print(json.load(sys.stdin).get('name',''))")
local base_url=$(echo "$provider" | python3 -c "import json,sys; print(json.load(sys.stdin).get('base_url',''))")
local token=$(echo "$provider" | python3 -c "import json,sys; print(json.load(sys.stdin).get('token',''))")
local model=$(echo "$provider" | python3 -c "import json,sys; print(json.load(sys.stdin).get('model',''))")
set_active_provider "$name"
update_settings "$base_url" "$token" "$model"
echo -e "${GREEN}已启用厂商: $name ($model)${NC}"
read -p "按回车继续..."
}
enable_provider_by_name() {
local name="$1"
local provider=$(get_provider_by_name "$name")
if [[ -z "$provider" ]]; then
echo -e "${RED}厂商不存在: $name${NC}"
return 1
fi
local base_url=$(echo "$provider" | python3 -c "import json,sys; print(json.load(sys.stdin).get('base_url',''))")
local token=$(echo "$provider" | python3 -c "import json,sys; print(json.load(sys.stdin).get('token',''))")
local model=$(echo "$provider" | python3 -c "import json,sys; print(json.load(sys.stdin).get('model',''))")
set_active_provider "$name"
update_settings "$base_url" "$token" "$model"
echo -e "${GREEN}已启用厂商: $name ($model)${NC}"
}
# 主循环
main() {
# 检查依赖
if ! command -v python3 &> /dev/null; then
echo -e "${RED}错误: 需要安装 python3${NC}"
exit 1
fi
# 初始化 settings.json(如果不存在或为空)
init_settings_file
# 初始化厂商配置文件
init_providers_file
while true; do
show_menu
read -p "请选择: " choice
case "$choice" in
a|A)
add_provider_dialog
;;
e|E)
edit_provider_dialog
;;
d|D)
delete_provider_dialog
;;
q|Q)
echo "再见!"
exit 0
;;
[0-9]*)
local count=$(get_provider_count)
if [[ "$choice" -ge 1 ]] && [[ "$choice" -le "$count" ]]; then
enable_provider_by_index $((choice-1))
else
echo -e "${RED}无效选择${NC}"
sleep 1
fi
;;
*)
echo -e "${RED}无效选择${NC}"
sleep 1
;;
esac
done
}
main "$@"
更多推荐



所有评论(0)