Spaces:
Sleeping
Sleeping
File size: 5,421 Bytes
00a2010 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | #!/usr/bin/env bash
# claude-pick — Interactive model picker for free-claude-code
# Usage: claude-pick [extra claude args...]
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODELS_FILE="$SCRIPT_DIR/nvidia_nim_models.json"
ENV_FILE="${CLAUDE_PICK_ENV_FILE:-$SCRIPT_DIR/.env}"
PORT="${CLAUDE_PICK_PORT:-8082}"
BASE_URL="http://localhost:$PORT"
OPENROUTER_MODELS_URL="https://openrouter.ai/api/v1/models"
DEFAULT_LM_STUDIO_BASE_URL="http://localhost:1234/v1"
DEFAULT_LLAMACPP_BASE_URL="http://localhost:8080/v1"
if ! command -v python3 >/dev/null 2>&1; then
echo "Error: python3 is required." >&2
exit 1
fi
read_env_value() {
local key="$1"
[[ -f "$ENV_FILE" ]] || return 0
local raw
raw="$(grep -E "^[[:space:]]*${key}[[:space:]]*=" "$ENV_FILE" | tail -n 1 || true)"
raw="${raw#*=}"
raw="${raw%%#*}"
raw="$(echo "$raw" | xargs || true)"
raw="${raw%\"}"
raw="${raw#\"}"
raw="${raw%\'}"
raw="${raw#\'}"
echo "$raw"
}
if ! command -v fzf >/dev/null 2>&1; then
echo "Error: fzf is required for the model picker." >&2
echo "Install it from: https://github.com/junegunn/fzf" >&2
exit 1
fi
parse_models_from_json() {
python3 -c '
import json, sys
try:
payload = json.load(sys.stdin)
except Exception:
sys.exit(0)
for item in payload.get("data", []):
model_id = item.get("id")
if model_id:
print(model_id)
'
}
get_nvidia_models() {
if [[ ! -f "$MODELS_FILE" ]]; then
echo "Error: $MODELS_FILE not found." >&2
echo "Run: curl \"https://integrate.api.nvidia.com/v1/models\" > nvidia_nim_models.json" >&2
exit 1
fi
python3 -c '
import json, sys
with open(sys.argv[1], "r", encoding="utf-8") as f:
payload = json.load(f)
for item in payload.get("data", []):
model_id = item.get("id")
if model_id:
print(model_id)
' "$MODELS_FILE"
}
get_openrouter_models() {
if ! command -v curl >/dev/null 2>&1; then
echo "Error: curl is required for OpenRouter model discovery." >&2
exit 1
fi
local openrouter_key
openrouter_key="${OPENROUTER_API_KEY:-$(read_env_value OPENROUTER_API_KEY)}"
local response
if [[ -n "$openrouter_key" ]]; then
if ! response="$(curl -fsSL -H "Authorization: Bearer $openrouter_key" "$OPENROUTER_MODELS_URL")"; then
echo "Error: Failed to fetch OpenRouter models." >&2
exit 1
fi
else
if ! response="$(curl -fsSL "$OPENROUTER_MODELS_URL")"; then
echo "Error: Failed to fetch OpenRouter models." >&2
exit 1
fi
fi
parse_models_from_json <<< "$response"
}
get_lmstudio_models() {
if ! command -v curl >/dev/null 2>&1; then
echo "Error: curl is required for LM Studio model discovery." >&2
exit 1
fi
local lm_base
lm_base="${LM_STUDIO_BASE_URL:-$(read_env_value LM_STUDIO_BASE_URL)}"
lm_base="${lm_base:-$DEFAULT_LM_STUDIO_BASE_URL}"
local models_url
if [[ "$lm_base" == */v1 ]]; then
models_url="${lm_base}/models"
else
models_url="${lm_base}/v1/models"
fi
local response
if ! response="$(curl -fsSL "$models_url")"; then
echo "Error: Failed to query LM Studio models at $models_url" >&2
echo "Start LM Studio server first (Developer tab or: lms server start)." >&2
exit 1
fi
parse_models_from_json <<< "$response"
}
provider="${CLAUDE_PICK_PROVIDER:-$(read_env_value PROVIDER_TYPE)}"
provider="${provider:-nvidia_nim}"
prompt="Select a model> "
case "$provider" in
nvidia_nim)
models="$(get_nvidia_models)"
prompt="Select a NVIDIA NIM model> "
;;
open_router|openrouter)
models="$(get_openrouter_models)"
prompt="Select an OpenRouter model> "
;;
lmstudio|lm_studio|lm-studio)
models="$(get_lmstudio_models)"
prompt="Select an LM Studio model> "
;;
llamacpp|llama.cpp)
# llama.cpp doesn't have a standardized /models endpoint that returns all loaded models reliably
# in the same way, but it does support Anthropic routing. We can use a stub model or query if available.
# For simple picker, we'll just allow passing a default or typing it in, but to match fzf we offer a stub.
models="local-model\nllama-server"
prompt="Select a llama.cpp model> "
;;
*)
echo "Error: Unsupported PROVIDER_TYPE='$provider'." >&2
echo "Expected one of: nvidia_nim, open_router, lmstudio, llamacpp" >&2
exit 1
;;
esac
models="$(printf "%s\n" "$models" | sed '/^[[:space:]]*$/d' | sort -u)"
if [[ -z "$models" ]]; then
echo "Error: No models found for provider '$provider'." >&2
exit 1
fi
model="$(printf "%s\n" "$models" | fzf --prompt="$prompt" --height=40% --reverse)"
if [[ -z "${model:-}" ]]; then
echo "No model selected." >&2
exit 1
fi
# Read auth token from .env or environment
auth_token="${ANTHROPIC_AUTH_TOKEN:-$(read_env_value ANTHROPIC_AUTH_TOKEN)}"
if [[ -z "$auth_token" ]]; then
auth_token="freecc"
fi
# If auth_token doesn't contain a colon, append ":$model"
if [[ "$auth_token" != *:* ]]; then
auth_token="$auth_token:$model"
fi
echo "Launching Claude with provider: $provider, model: $model" >&2
ANTHROPIC_AUTH_TOKEN="$auth_token" ANTHROPIC_BASE_URL="$BASE_URL" exec claude "$@"
|