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 "$@"

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐