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_env_vars --description "Return list of environment variables set by configure"
 38    echo ANTHROPIC_BASE_URL
 39    echo ANTHROPIC_AUTH_TOKEN
 40    echo ANTHROPIC_DEFAULT_OPUS_MODEL
 41    echo ANTHROPIC_DEFAULT_SONNET_MODEL
 42    echo ANTHROPIC_DEFAULT_HAIKU_MODEL
 43    echo CLAUDE_CODE_SUBAGENT_MODEL
 44    echo CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
 45end
 46
 47function _synu_agent_claude_configure --description "Configure Claude Code environment variables"
 48    # Parse flags passed from main synu
 49    argparse 'L/large=' 'l/light=' 'o/opus=' 's/sonnet=' 'H/haiku=' 'a/agent=' -- $argv
 50    or return 1
 51
 52    # Start with defaults (from cache or fallback)
 53    set -l opus_model (_synu_claude_default opus)
 54    set -l sonnet_model (_synu_claude_default sonnet)
 55    set -l haiku_model (_synu_claude_default haiku)
 56    set -l subagent_model (_synu_claude_default agent)
 57
 58    # Apply group overrides
 59    if set -q _flag_large
 60        set opus_model $_flag_large
 61        set sonnet_model $_flag_large
 62        set subagent_model $_flag_large
 63    end
 64
 65    if set -q _flag_light
 66        set haiku_model $_flag_light
 67    end
 68
 69    # Apply specific overrides (take precedence over groups)
 70    if set -q _flag_opus
 71        set opus_model $_flag_opus
 72    end
 73    if set -q _flag_sonnet
 74        set sonnet_model $_flag_sonnet
 75    end
 76    if set -q _flag_haiku
 77        set haiku_model $_flag_haiku
 78    end
 79    if set -q _flag_agent
 80        set subagent_model $_flag_agent
 81    end
 82
 83    # Export environment variables for Claude Code
 84    set -gx ANTHROPIC_BASE_URL "https://api.synthetic.new/anthropic"
 85    set -gx ANTHROPIC_AUTH_TOKEN $SYNTHETIC_API_KEY
 86    set -gx ANTHROPIC_DEFAULT_OPUS_MODEL $opus_model
 87    set -gx ANTHROPIC_DEFAULT_SONNET_MODEL $sonnet_model
 88    set -gx ANTHROPIC_DEFAULT_HAIKU_MODEL $haiku_model
 89    set -gx CLAUDE_CODE_SUBAGENT_MODEL $subagent_model
 90    set -gx CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC 1
 91end
 92
 93function _synu_agent_claude_interactive --description "Interactive model selection using gum"
 94    # Check for gum
 95    if not command -q gum
 96        echo "Error: gum is required for interactive mode. Install: https://github.com/charmbracelet/gum" >&2
 97        return 1
 98    end
 99
100    # Fetch available models
101    set -l models_json (gum spin --spinner dot --title "Fetching models..." -- \
102        curl -s -H "Authorization: Bearer $SYNTHETIC_API_KEY" \
103        "https://api.synthetic.new/openai/v1/models")
104    or return 1
105
106    set -l model_names (echo $models_json | jq -r '.data[].name')
107    or return 1
108
109    # Prompt for groups vs individual
110    set -l mode (gum choose --limit 1 --header "How do you want to select models?" \
111        "Groups" "Individual models")
112    or return 1
113
114    # Build flags array
115    set -l flags
116
117    if test "$mode" = "Groups"
118        # Select which groups to override
119        set -l groups (gum choose --no-limit \
120            --header "Which group(s) do you want to override?" \
121            "Large (Opus, Sonnet, Sub-agent)" "Light (Haiku)")
122        or return 1
123
124        for group in $groups
125            if test "$group" = "Large (Opus, Sonnet, Sub-agent)"
126                set -l model_name (printf "%s\n" $model_names | \
127                    gum filter --limit 1 --header "Select model for Large 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 --large=$model_id
134                end
135            else if test "$group" = "Light (Haiku)"
136                set -l model_name (printf "%s\n" $model_names | \
137                    gum filter --limit 1 --header "Select model for Light group" \
138                    --placeholder "Filter models...")
139                or return 1
140                set -l model_id (echo $models_json | \
141                    jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
142                if test -n "$model_id"
143                    set flags $flags --light=$model_id
144                end
145            end
146        end
147    else
148        # Select which individual models to override
149        set -l models (gum choose --no-limit \
150            --header "Which model(s) do you want to override?" \
151            "Opus" "Sonnet" "Haiku" "Sub-agent")
152        or return 1
153
154        for model_type in $models
155            switch $model_type
156                case "Opus"
157                    set -l model_name (printf "%s\n" $model_names | \
158                        gum filter --limit 1 --header "Select Opus 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 --opus=$model_id
165                    end
166                case "Sonnet"
167                    set -l model_name (printf "%s\n" $model_names | \
168                        gum filter --limit 1 --header "Select Sonnet 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 --sonnet=$model_id
175                    end
176                case "Haiku"
177                    set -l model_name (printf "%s\n" $model_names | \
178                        gum filter --limit 1 --header "Select Haiku 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 --haiku=$model_id
185                    end
186                case "Sub-agent"
187                    set -l model_name (printf "%s\n" $model_names | \
188                        gum filter --limit 1 --header "Select Sub-agent model" \
189                        --placeholder "Filter models...")
190                    or return 1
191                    set -l model_id (echo $models_json | \
192                        jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
193                    if test -n "$model_id"
194                        set flags $flags --agent=$model_id
195                    end
196            end
197        end
198    end
199
200    # Offer to save as defaults
201    if test (count $flags) -gt 0
202        if gum confirm "Save as default for 'claude'?"
203            for flag in $flags
204                # Parse --key=value format
205                set -l parts (string match -r -- '^--([^=]+)=(.+)$' $flag)
206                if test -n "$parts[2]"
207                    set -l key $parts[2]
208                    set -l value $parts[3]
209                    # Expand group flags to individual slots
210                    switch $key
211                        case large
212                            _synu_cache_set claude opus $value
213                            _synu_cache_set claude sonnet $value
214                            _synu_cache_set claude agent $value
215                        case light
216                            _synu_cache_set claude haiku $value
217                        case '*'
218                            _synu_cache_set claude $key $value
219                    end
220                end
221            end
222        end
223    end
224
225    # Output flags for caller to use
226    echo $flags
227end