Last active
November 21, 2025 11:54
-
-
Save thoroc/9d8e5b06cc85c7526258f90559af7840 to your computer and use it in GitHub Desktop.
Check which models is currently set across all the Opencode related files on the system
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| shopt -s nullglob | |
| # opencode-model-check.sh - Check currently used model in OpenCode logs | |
| # | |
| # Requirements: | |
| # REQUIRED: | |
| # - jq: JSON processor (https://jqlang.github.io/jq/) | |
| # - grep: Text search utility (standard on all Unix systems) | |
| # - Standard Unix tools: find, ls, du, basename, cut, sed, awk, head, tr, xargs | |
| # | |
| # OPTIONAL (automatically used if available): | |
| # - rg (ripgrep): Faster text search (https://github.com/BurntSushi/ripgrep) | |
| # Script automatically uses rg when available, falls back to grep | |
| # | |
| # Installation: | |
| # • macOS: brew install jq ripgrep | |
| # • Linux: apt-get install jq ripgrep (Debian/Ubuntu) | |
| # yum install jq ripgrep (RHEL/CentOS) | |
| # • mise: mise install jq ripgrep | |
| # | |
| # Usage: | |
| # opencode-model-check.sh # Show current model | |
| # opencode-model-check.sh gpt # Search for 'gpt' models | |
| # opencode-model-check.sh --history # Show model usage history | |
| # Tool availability checks | |
| # jq: Required for JSON operations (no fallback) | |
| # grep: Required for all operations (no fallback) | |
| # rg (ripgrep): Optional, falls back to grep if not available | |
| # Check for required tool: grep | |
| if ! command -v grep >/dev/null 2>&1; then | |
| echo "Error: grep is required but not found in PATH" >&2 | |
| echo "Please install grep or ensure it's in your PATH" >&2 | |
| exit 1 | |
| fi | |
| # Check for required tool: jq | |
| if ! command -v jq >/dev/null 2>&1; then | |
| echo "Error: jq is required but not found in PATH" >&2 | |
| echo "" >&2 | |
| echo "Install jq using one of these methods:" >&2 | |
| echo " • macOS: brew install jq" >&2 | |
| echo " • Linux: apt-get install jq (Debian/Ubuntu)" >&2 | |
| echo " yum install jq (RHEL/CentOS)" >&2 | |
| echo " • mise: mise install jq" >&2 | |
| echo "" >&2 | |
| echo "Or download from: https://jqlang.github.io/jq/download/" >&2 | |
| exit 1 | |
| fi | |
| # Check for optional tool: rg (ripgrep) | |
| # Prefer ripgrep when available for better performance, fallback to grep | |
| if command -v rg >/dev/null 2>&1; then | |
| GREP_CMD="rg" | |
| GREP_NO_FILENAME="-I" # ripgrep uses -I for --no-filename | |
| GREP_BRACE="\{" # ripgrep requires escaped brace | |
| else | |
| GREP_CMD="grep" | |
| GREP_NO_FILENAME="-h" # grep uses -h to suppress filename | |
| GREP_BRACE="{" # grep uses literal brace | |
| fi | |
| # OpenCode directories | |
| OPENCODE_CONFIG_DIR="${HOME}/.config/opencode" | |
| OPENCODE_SHARE_DIR="${HOME}/.local/share/opencode" | |
| OPENCODE_STATE_DIR="${HOME}/.local/state/opencode" | |
| OPENCODE_CACHE_DIR="${HOME}/.cache/opencode" | |
| LOG_DIR="${OPENCODE_SHARE_DIR}/log" | |
| CONFIG_FILE="${OPENCODE_CONFIG_DIR}/opencode.json" | |
| AUTH_FILE="${OPENCODE_SHARE_DIR}/auth.json" | |
| SNAPSHOT_DIR="${OPENCODE_SHARE_DIR}/snapshot" | |
| MODEL_STATE_FILE="${OPENCODE_STATE_DIR}/model.json" | |
| # Colors | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| BLUE='\033[0;34m' | |
| NC='\033[0m' # No Color | |
| # Helper function to replace home directory with ~ | |
| tildify() { | |
| sed "s|${HOME}|~|g" | |
| } | |
| usage() { | |
| cat << EOF | |
| Usage: $(basename "$0") [OPTIONS] [SEARCH_TERM] | |
| Check currently used model in OpenCode or search for specific models. | |
| OPTIONS: | |
| -h, --help Show this help message | |
| --history Show model usage history across all logs | |
| --config Show model configuration from opencode.json | |
| --all Show all unique models used | |
| --dirs Show OpenCode directory locations | |
| --providers Show configured authentication providers | |
| --json Output current model information as JSON | |
| EXAMPLES: | |
| $(basename "$0") # Show current model | |
| $(basename "$0") gpt # Find logs using GPT models | |
| $(basename "$0") claude # Find logs using Claude models | |
| $(basename "$0") --history # Show chronological model history | |
| EOF | |
| exit 0 | |
| } | |
| show_directories() { | |
| echo -e "${BLUE}OpenCode directories:${NC}" | |
| echo | |
| local dirs=( | |
| "Config:${OPENCODE_CONFIG_DIR}" | |
| "Data:${OPENCODE_SHARE_DIR}" | |
| "State:${OPENCODE_STATE_DIR}" | |
| "Cache:${OPENCODE_CACHE_DIR}" | |
| "Logs:${LOG_DIR}" | |
| "Snapshots:${SNAPSHOT_DIR}" | |
| ) | |
| for dir_info in "${dirs[@]}"; do | |
| local label="${dir_info%%:*}" | |
| local path="${dir_info#*:}" | |
| local display_path | |
| display_path=$(echo "$path" | tildify) | |
| if [[ -d "$path" ]]; then | |
| local size | |
| # For Data directory, exclude log/ and snapshot/ subdirectories from size calculation | |
| if [[ "$label" == "Data" ]]; then | |
| # Calculate size excluding log and snapshot subdirectories | |
| # Use find to sum sizes of all files/dirs except log and snapshot | |
| size=$(find "$path" -mindepth 1 -maxdepth 1 ! -name log ! -name snapshot -exec du -sk {} + 2>/dev/null | awk '{sum+=$1} END { | |
| if (sum >= 1048576) printf "%.1fG\n", sum/1048576 | |
| else if (sum >= 1024) printf "%.0fM\n", sum/1024 | |
| else printf "%dK\n", sum | |
| }') | |
| else | |
| size=$(du -sh "$path" 2>/dev/null | cut -f1 | tr -d ' ') | |
| fi | |
| echo -e " ${GREEN}✓${NC} ${label}: ${display_path} (${size})" | |
| else | |
| echo -e " ${RED}✗${NC} ${label}: ${display_path} (not found)" | |
| fi | |
| done | |
| echo | |
| } | |
| show_providers() { | |
| echo -e "${BLUE}Authentication providers:${NC}" | |
| if [[ -f "$AUTH_FILE" ]]; then | |
| echo | |
| local providers | |
| providers=$($GREP_CMD -o "\"[^\"]*\":[[:space:]]*$GREP_BRACE" "$AUTH_FILE" | cut -d'"' -f2) | |
| if [[ -n "$providers" ]]; then | |
| while IFS= read -r provider; do | |
| local type | |
| type=$($GREP_CMD -A1 "\"$provider\"" "$AUTH_FILE" | $GREP_CMD '"type"' | cut -d'"' -f4) | |
| echo -e " ${GREEN}$provider${NC} (${type})" | |
| done <<< "$providers" | |
| else | |
| echo " No providers configured" | |
| fi | |
| else | |
| local display_path | |
| display_path=$(echo "$AUTH_FILE" | tildify) | |
| echo " Auth file not found: $display_path" | |
| fi | |
| echo | |
| } | |
| show_recent_models() { | |
| if [[ -f "$MODEL_STATE_FILE" ]]; then | |
| echo -e "${BLUE}Recent model selections:${NC}" | |
| jq -r '.recent[] | " \(.providerID) → \(.modelID)"' "$MODEL_STATE_FILE" 2>/dev/null | |
| echo | |
| fi | |
| } | |
| check_config() { | |
| local display_dir | |
| display_dir=$(echo "$OPENCODE_CONFIG_DIR" | tildify) | |
| echo -e "${BLUE}Configuration (${display_dir}):${NC}" | |
| if [[ -f "$CONFIG_FILE" ]]; then | |
| if $GREP_CMD -q '"model"' "$CONFIG_FILE" 2>/dev/null; then | |
| $GREP_CMD -E '"model"|"provider"' "$CONFIG_FILE" | sed 's/^/ /' | |
| else | |
| echo " No explicit model configuration found (using default)" | |
| fi | |
| else | |
| echo " Config file not found" | |
| fi | |
| echo | |
| } | |
| get_current_model() { | |
| local latest_log | |
| # Find the most recent log file | |
| latest_log=$(find "$LOG_DIR" -name "*.log" -type f -print0 2>/dev/null | xargs -0 ls -t 2>/dev/null | head -1) | |
| if [[ -z "$latest_log" ]]; then | |
| echo -e "${RED}No log files found${NC}" >&2 | |
| return 1 | |
| fi | |
| local model | |
| model=$($GREP_CMD -o '"model":"[^"]*"' "$latest_log" 2>/dev/null | head -1 | cut -d'"' -f4 || true) | |
| if [[ -n "$model" ]]; then | |
| echo -e "${GREEN}Current model:${NC} ${YELLOW}$model${NC}" | |
| echo -e "${BLUE}From log:${NC} $(basename "$latest_log")" | |
| else | |
| echo -e "${YELLOW}No model found in latest log${NC}" | |
| echo -e "${BLUE}Latest log:${NC} $(basename "$latest_log")" | |
| fi | |
| } | |
| show_history() { | |
| echo -e "${BLUE}Model usage history:${NC}" | |
| echo | |
| local found=0 | |
| local logs=("$LOG_DIR"/*.log) | |
| # Sort by modification time (newest first) | |
| if [[ ${#logs[@]} -gt 0 && -f "${logs[0]}" ]]; then | |
| while IFS= read -r -d '' log; do | |
| local model | |
| model=$($GREP_CMD -o '"model":"[^"]*"' "$log" 2>/dev/null | head -1 | cut -d'"' -f4 || true) | |
| if [[ -n "$model" ]]; then | |
| local timestamp | |
| timestamp=$(basename "$log" .log) | |
| echo -e " ${GREEN}$timestamp${NC} → ${YELLOW}$model${NC}" | |
| found=1 | |
| fi | |
| done < <(find "$LOG_DIR" -name "*.log" -type f -print0 2>/dev/null | xargs -0 ls -t 2>/dev/null | tr '\n' '\0') | |
| fi | |
| if [[ $found -eq 0 ]]; then | |
| echo -e " ${YELLOW}No model information found in logs${NC}" | |
| fi | |
| } | |
| show_all_models() { | |
| echo -e "${BLUE}All unique models used:${NC}" | |
| echo | |
| local models | |
| models=$($GREP_CMD $GREP_NO_FILENAME '"model":"[^"]*"' "$LOG_DIR"/*.log 2>/dev/null | \ | |
| $GREP_CMD -o '"model":"[^"]*"' | \ | |
| cut -d'"' -f4 | \ | |
| sort -u) | |
| if [[ -n "$models" ]]; then | |
| while IFS= read -r model; do | |
| local count | |
| count=$($GREP_CMD $GREP_NO_FILENAME -cF "\"model\":\"$model\"" "$LOG_DIR"/*.log 2>/dev/null | awk '{s+=$1} END {print s}') | |
| echo -e " ${YELLOW}$model${NC} (used in $count requests)" | |
| done <<< "$models" | |
| else | |
| echo -e " ${YELLOW}No models found in logs${NC}" | |
| fi | |
| } | |
| search_model() { | |
| local search_term="$1" | |
| echo -e "${BLUE}Searching for models matching '${search_term}':${NC}" | |
| echo | |
| local found=0 | |
| local logs=("$LOG_DIR"/*.log) | |
| # Sort by modification time (newest first) | |
| if [[ ${#logs[@]} -gt 0 && -f "${logs[0]}" ]]; then | |
| while IFS= read -r -d '' log; do | |
| local model | |
| model=$($GREP_CMD -o '"model":"[^"]*"' "$log" 2>/dev/null | head -1 | cut -d'"' -f4 || true) | |
| if [[ -n "$model" ]] && [[ "$model" =~ $search_term ]]; then | |
| local timestamp | |
| timestamp=$(basename "$log" .log) | |
| echo -e " ${GREEN}$timestamp${NC} → ${YELLOW}$model${NC}" | |
| found=1 | |
| fi | |
| done < <(find "$LOG_DIR" -name "*.log" -type f -print0 2>/dev/null | xargs -0 ls -t 2>/dev/null | tr '\n' '\0') | |
| fi | |
| if [[ $found -eq 0 ]]; then | |
| echo -e " ${YELLOW}No matching models found${NC}" | |
| fi | |
| } | |
| output_json() { | |
| local latest_log | |
| # Find the most recent log file | |
| latest_log=$(find "$LOG_DIR" -name "*.log" -type f -print0 2>/dev/null | xargs -0 ls -t 2>/dev/null | head -1) | |
| if [[ -z "$latest_log" ]]; then | |
| echo '{"error": "No log files found"}' >&2 | |
| exit 1 | |
| fi | |
| local model | |
| local provider | |
| local timestamp | |
| model=$($GREP_CMD -o '"model":"[^"]*"' "$latest_log" 2>/dev/null | head -1 | cut -d'"' -f4 || true) | |
| provider=$($GREP_CMD -o '"provider":"[^"]*"' "$latest_log" 2>/dev/null | head -1 | cut -d'"' -f4 || true) | |
| timestamp=$(basename "$latest_log" .log) | |
| # Build JSON output (jq is required and checked at script start) | |
| jq -n \ | |
| --arg model "${model:-null}" \ | |
| --arg provider "${provider:-null}" \ | |
| --arg log "$timestamp" \ | |
| --arg log_path "$latest_log" \ | |
| '{ | |
| model: $model, | |
| provider: $provider, | |
| log: $log, | |
| log_path: $log_path, | |
| timestamp: $log | |
| }' | |
| } | |
| # Main script | |
| if [[ ! -d "$LOG_DIR" ]]; then | |
| echo -e "${RED}Error: Log directory not found: $LOG_DIR${NC}" >&2 | |
| exit 1 | |
| fi | |
| case "${1:-}" in | |
| -h|--help) | |
| usage | |
| ;; | |
| --dirs) | |
| show_directories | |
| ;; | |
| --providers) | |
| show_providers | |
| ;; | |
| --config) | |
| check_config | |
| ;; | |
| --history) | |
| show_history | |
| ;; | |
| --all) | |
| show_all_models | |
| ;; | |
| --json) | |
| output_json | |
| ;; | |
| "") | |
| show_directories | |
| check_config | |
| show_recent_models | |
| show_providers | |
| get_current_model | |
| ;; | |
| *) | |
| search_model "$1" | |
| ;; | |
| esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment