claude.fish

  1# SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
  2#
  3# SPDX-License-Identifier: Unlicense
  4
  5# Claude Code agent definition for synu
  6# Provides model configuration for routing through Synthetic API
  7
  8# Source cache functions
  9source (status dirname)/../_synu_cache.fish
 10
 11# Fallback defaults (used when no cache entry exists)
 12set -g _synu_claude_fallback_opus "hf:moonshotai/Kimi-K2-Thinking"
 13set -g _synu_claude_fallback_sonnet "hf:MiniMaxAI/MiniMax-M2"
 14set -g _synu_claude_fallback_haiku "hf:deepseek-ai/DeepSeek-V3.1-Terminus"
 15set -g _synu_claude_fallback_agent "hf:MiniMaxAI/MiniMax-M2"
 16
 17function _synu_claude_default --description "Get default model: _synu_claude_default slot"
 18    set -l slot $argv[1]
 19    set -l cached (_synu_cache_get claude $slot)
 20    if test $status -eq 0
 21        echo $cached
 22    else
 23        set -l var_name _synu_claude_fallback_$slot
 24        echo $$var_name
 25    end
 26end
 27
 28function _synu_agent_claude_flags --description "Return argparse-compatible flag specification"
 29    echo "L/large="
 30    echo "l/light="
 31    echo "o/opus="
 32    echo "s/sonnet="
 33    echo "H/haiku="
 34    echo "a/agent="
 35end
 36
 37function _synu_agent_claude_configure --description "Configure Claude Code environment variables"
 38    # Parse flags passed from main synu
 39    argparse 'L/large=' 'l/light=' 'o/opus=' 's/sonnet=' 'H/haiku=' 'a/agent=' -- $argv
 40    or return 1
 41
 42    # Start with defaults (from cache or fallback)
 43    set -l opus_model (_synu_claude_default opus)
 44    set -l sonnet_model (_synu_claude_default sonnet)
 45    set -l haiku_model (_synu_claude_default haiku)
 46    set -l subagent_model (_synu_claude_default agent)
 47
 48    # Apply group overrides
 49    if set -q _flag_large
 50        set opus_model $_flag_large
 51        set sonnet_model $_flag_large
 52        set subagent_model $_flag_large
 53    end
 54
 55    if set -q _flag_light
 56        set haiku_model $_flag_light
 57    end
 58
 59    # Apply specific overrides (take precedence over groups)
 60    if set -q _flag_opus
 61        set opus_model $_flag_opus
 62    end
 63    if set -q _flag_sonnet
 64        set sonnet_model $_flag_sonnet
 65    end
 66    if set -q _flag_haiku
 67        set haiku_model $_flag_haiku
 68    end
 69    if set -q _flag_agent
 70        set subagent_model $_flag_agent
 71    end
 72
 73    # Export environment variables for Claude Code
 74    set -gx ANTHROPIC_BASE_URL "https://api.synthetic.new/anthropic"
 75    set -gx ANTHROPIC_AUTH_TOKEN $SYNTHETIC_API_KEY
 76    set -gx ANTHROPIC_DEFAULT_OPUS_MODEL $opus_model
 77    set -gx ANTHROPIC_DEFAULT_SONNET_MODEL $sonnet_model
 78    set -gx ANTHROPIC_DEFAULT_HAIKU_MODEL $haiku_model
 79    set -gx CLAUDE_CODE_SUBAGENT_MODEL $subagent_model
 80    set -gx CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC 1
 81end
 82
 83function _synu_agent_claude_interactive --description "Interactive model selection using gum"
 84    # Check for gum
 85    if not command -q gum
 86        echo "Error: gum is required for interactive mode. Install: https://github.com/charmbracelet/gum" >&2
 87        return 1
 88    end
 89
 90    # Fetch available models
 91    set -l models_json (gum spin --spinner dot --title "Fetching models..." -- \
 92        curl -s -H "Authorization: Bearer $SYNTHETIC_API_KEY" \
 93        "https://api.synthetic.new/openai/v1/models")
 94    or return 1
 95
 96    set -l model_names (echo $models_json | jq -r '.data[].name')
 97    or return 1
 98
 99    # Prompt for groups vs individual
100    set -l mode (gum choose --limit 1 --header "How do you want to select models?" \
101        "Groups" "Individual models")
102    or return 1
103
104    # Build flags array
105    set -l flags
106
107    if test "$mode" = "Groups"
108        # Select which groups to override
109        set -l groups (gum choose --no-limit \
110            --header "Which group(s) do you want to override?" \
111            "Large (Opus, Sonnet, Sub-agent)" "Light (Haiku)")
112        or return 1
113
114        for group in $groups
115            if test "$group" = "Large (Opus, Sonnet, Sub-agent)"
116                set -l model_name (printf "%s\n" $model_names | \
117                    gum filter --limit 1 --header "Select model for Large group" \
118                    --placeholder "Filter models...")
119                or return 1
120                set -l model_id (echo $models_json | \
121                    jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
122                if test -n "$model_id"
123                    set flags $flags --large=$model_id
124                end
125            else if test "$group" = "Light (Haiku)"
126                set -l model_name (printf "%s\n" $model_names | \
127                    gum filter --limit 1 --header "Select model for Light group" \
128                    --placeholder "Filter models...")
129                or return 1
130                set -l model_id (echo $models_json | \
131                    jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
132                if test -n "$model_id"
133                    set flags $flags --light=$model_id
134                end
135            end
136        end
137    else
138        # Select which individual models to override
139        set -l models (gum choose --no-limit \
140            --header "Which model(s) do you want to override?" \
141            "Opus" "Sonnet" "Haiku" "Sub-agent")
142        or return 1
143
144        for model_type in $models
145            switch $model_type
146                case "Opus"
147                    set -l model_name (printf "%s\n" $model_names | \
148                        gum filter --limit 1 --header "Select Opus model" \
149                        --placeholder "Filter models...")
150                    or return 1
151                    set -l model_id (echo $models_json | \
152                        jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
153                    if test -n "$model_id"
154                        set flags $flags --opus=$model_id
155                    end
156                case "Sonnet"
157                    set -l model_name (printf "%s\n" $model_names | \
158                        gum filter --limit 1 --header "Select Sonnet model" \
159                        --placeholder "Filter models...")
160                    or return 1
161                    set -l model_id (echo $models_json | \
162                        jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
163                    if test -n "$model_id"
164                        set flags $flags --sonnet=$model_id
165                    end
166                case "Haiku"
167                    set -l model_name (printf "%s\n" $model_names | \
168                        gum filter --limit 1 --header "Select Haiku model" \
169                        --placeholder "Filter models...")
170                    or return 1
171                    set -l model_id (echo $models_json | \
172                        jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
173                    if test -n "$model_id"
174                        set flags $flags --haiku=$model_id
175                    end
176                case "Sub-agent"
177                    set -l model_name (printf "%s\n" $model_names | \
178                        gum filter --limit 1 --header "Select Sub-agent model" \
179                        --placeholder "Filter models...")
180                    or return 1
181                    set -l model_id (echo $models_json | \
182                        jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
183                    if test -n "$model_id"
184                        set flags $flags --agent=$model_id
185                    end
186            end
187        end
188    end
189
190    # Offer to save as defaults
191    if test (count $flags) -gt 0
192        if gum confirm "Save as default for 'claude'?"
193            for flag in $flags
194                # Parse --key=value format
195                set -l parts (string match -r '^--([^=]+)=(.+)$' $flag)
196                if test -n "$parts[2]"
197                    set -l key $parts[2]
198                    set -l value $parts[3]
199                    # Expand group flags to individual slots
200                    switch $key
201                        case large
202                            _synu_cache_set claude opus $value
203                            _synu_cache_set claude sonnet $value
204                            _synu_cache_set claude agent $value
205                        case light
206                            _synu_cache_set claude haiku $value
207                        case '*'
208                            _synu_cache_set claude $key $value
209                    end
210                end
211            end
212        end
213    end
214
215    # Output flags for caller to use
216    echo $flags
217end