refactor(claude): add medium tier to model groups

Amolith created

- Heavy (-H/--heavy): Opus only
- Medium (-M/--medium): Sonnet + Subagent
- Light (-l/--light): Haiku

Individual slot overrides unchanged except -H/--haiku → -k/--haiku to
avoid conflict with new -H/--heavy flag.

Assisted-by: Claude Sonnet 4 via Crush

Change summary

README.md                               |  7 ++-
fish/functions/_synu_agents/claude.fish | 39 ++++++++++++++++-------
zsh/functions/_synu_agents/claude.zsh   | 43 +++++++++++++++++++-------
3 files changed, 62 insertions(+), 27 deletions(-)

Detailed changes

README.md 🔗

@@ -159,11 +159,12 @@ synu claude --haiku hf:other/model
 synu claude --agent hf:other/model
 
 # Group overrides
-synu claude --large hf:model   # Sets Opus, Sonnet, and Subagent
-synu claude --light hf:model   # Sets Haiku
+synu claude --heavy hf:model    # Sets Opus
+synu claude --medium hf:model   # Sets Sonnet and Subagent
+synu claude --light hf:model    # Sets Haiku
 
 # Non-interactive with model override
-synu claude --large hf:model -p "What does this code do?"
+synu claude --heavy hf:model -p "What does this code do?"
 ```
 
 ### OpenCode

fish/functions/_synu_agents/claude.fish 🔗

@@ -26,11 +26,12 @@ function _synu_claude_default --description "Get default model: _synu_claude_def
 end
 
 function _synu_agent_claude_flags --description "Return argparse-compatible flag specification"
-    echo "L/large="
+    echo "H/heavy="
+    echo "M/medium="
     echo "l/light="
     echo "o/opus="
     echo "s/sonnet="
-    echo "H/haiku="
+    echo "k/haiku="
     echo "a/agent="
 end
 
@@ -46,7 +47,7 @@ end
 
 function _synu_agent_claude_configure --description "Configure Claude Code environment variables"
     # Parse flags passed from main synu
-    argparse 'L/large=' 'l/light=' 'o/opus=' 's/sonnet=' 'H/haiku=' 'a/agent=' -- $argv
+    argparse 'H/heavy=' 'M/medium=' 'l/light=' 'o/opus=' 's/sonnet=' 'k/haiku=' 'a/agent=' -- $argv
     or return 1
 
     # Start with defaults (from cache or fallback)
@@ -56,10 +57,13 @@ function _synu_agent_claude_configure --description "Configure Claude Code envir
     set -l subagent_model (_synu_claude_default agent)
 
     # Apply group overrides
-    if set -q _flag_large
-        set opus_model $_flag_large
-        set sonnet_model $_flag_large
-        set subagent_model $_flag_large
+    if set -q _flag_heavy
+        set opus_model $_flag_heavy
+    end
+
+    if set -q _flag_medium
+        set sonnet_model $_flag_medium
+        set subagent_model $_flag_medium
     end
 
     if set -q _flag_light
@@ -132,19 +136,29 @@ function _synu_agent_claude_interactive --description "Interactive model selecti
         # Select which groups to override
         set -l groups (gum choose --no-limit \
             --header "Which group(s) do you want to override?" \
-            "Large (Opus, Sonnet, Sub-agent)" "Light (Haiku)")
+            "Heavy (Opus)" "Medium (Sonnet, Sub-agent)" "Light (Haiku)")
         or return 1
 
         for group in $groups
-            if test "$group" = "Large (Opus, Sonnet, Sub-agent)"
+            if test "$group" = "Heavy (Opus)"
+                set -l model_name (printf "%s\n" $model_names | \
+                    gum filter --limit 1 --header "Select model for Heavy group (opus: $current_opus_id)" \
+                    --placeholder "Filter models...")
+                or return 1
+                set -l model_id (echo $models_json | \
+                    jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
+                if test -n "$model_id"
+                    set flags $flags --heavy=$model_id
+                end
+            else if test "$group" = "Medium (Sonnet, Sub-agent)"
                 set -l model_name (printf "%s\n" $model_names | \
-                    gum filter --limit 1 --header "Select model for Large group (opus: $current_opus_id, sonnet: $current_sonnet_id, agent: $current_agent_id)" \
+                    gum filter --limit 1 --header "Select model for Medium group (sonnet: $current_sonnet_id, agent: $current_agent_id)" \
                     --placeholder "Filter models...")
                 or return 1
                 set -l model_id (echo $models_json | \
                     jq -r --arg name "$model_name" '.data[] | select(.name == $name) | .id')
                 if test -n "$model_id"
-                    set flags $flags --large=$model_id
+                    set flags $flags --medium=$model_id
                 end
             else if test "$group" = "Light (Haiku)"
                 set -l model_name (printf "%s\n" $model_names | \
@@ -222,8 +236,9 @@ function _synu_agent_claude_interactive --description "Interactive model selecti
                     set -l value $parts[3]
                     # Expand group flags to individual slots
                     switch $key
-                        case large
+                        case heavy
                             _synu_cache_set claude opus $value
+                        case medium
                             _synu_cache_set claude sonnet $value
                             _synu_cache_set claude agent $value
                         case light

zsh/functions/_synu_agents/claude.zsh 🔗

@@ -24,11 +24,12 @@ _synu_claude_default() {
 }
 
 _synu_agent_claude_flags() {
-    echo "L/large="
+    echo "H/heavy="
+    echo "M/medium="
     echo "l/light="
     echo "o/opus="
     echo "s/sonnet="
-    echo "H/haiku="
+    echo "k/haiku="
     echo "a/agent="
 }
 
@@ -49,7 +50,8 @@ _synu_agent_claude_configure() {
     # Parse flags passed from main synu
     while [[ $# -gt 0 ]]; do
         case "$1" in
-            --large=*) opts[large]="${1#*=}" ;;
+            --heavy=*) opts[heavy]="${1#*=}" ;;
+            --medium=*) opts[medium]="${1#*=}" ;;
             --light=*) opts[light]="${1#*=}" ;;
             --opus=*) opts[opus]="${1#*=}" ;;
             --sonnet=*) opts[sonnet]="${1#*=}" ;;
@@ -67,10 +69,13 @@ _synu_agent_claude_configure() {
     local subagent_model=$(_synu_claude_default agent)
 
     # Apply group overrides
-    if [[ -n "${opts[large]}" ]]; then
-        opus_model="${opts[large]}"
-        sonnet_model="${opts[large]}"
-        subagent_model="${opts[large]}"
+    if [[ -n "${opts[heavy]}" ]]; then
+        opus_model="${opts[heavy]}"
+    fi
+
+    if [[ -n "${opts[medium]}" ]]; then
+        sonnet_model="${opts[medium]}"
+        subagent_model="${opts[medium]}"
     fi
 
     if [[ -n "${opts[light]}" ]]; then
@@ -140,22 +145,34 @@ _synu_agent_claude_interactive() {
         local -a groups
         groups=("${(@f)$(gum choose --no-limit \
             --header "Which group(s) do you want to override?" \
-            "Large (Opus, Sonnet, Sub-agent)" "Light (Haiku)")}")
+            "Heavy (Opus)" "Medium (Sonnet, Sub-agent)" "Light (Haiku)")}")
         [[ $? -ne 0 ]] && return 1
 
         local group
         for group in "${groups[@]}"; do
-            if [[ "${group}" == "Large (Opus, Sonnet, Sub-agent)" ]]; then
+            if [[ "${group}" == "Heavy (Opus)" ]]; then
+                local model_name
+                model_name=$(printf "%s\n" "${model_names[@]}" | \
+                    gum filter --limit 1 --header "Select model for Heavy group (opus: ${current_opus_name})" \
+                    --placeholder "Filter models...")
+                [[ $? -ne 0 ]] && return 1
+
+                local model_id
+                model_id=$(echo "${models_json}" | \
+                    jq -r --arg name "${model_name}" '.data[] | select(.name == $name) | .id')
+                [[ -n "${model_id}" ]] && flags+=(--heavy="${model_id}")
+
+            elif [[ "${group}" == "Medium (Sonnet, Sub-agent)" ]]; then
                 local model_name
                 model_name=$(printf "%s\n" "${model_names[@]}" | \
-                    gum filter --limit 1 --header "Select model for Large group (opus: ${current_opus_name}, sonnet: ${current_sonnet_name}, agent: ${current_agent_name})" \
+                    gum filter --limit 1 --header "Select model for Medium group (sonnet: ${current_sonnet_name}, agent: ${current_agent_name})" \
                     --placeholder "Filter models...")
                 [[ $? -ne 0 ]] && return 1
 
                 local model_id
                 model_id=$(echo "${models_json}" | \
                     jq -r --arg name "${model_name}" '.data[] | select(.name == $name) | .id')
-                [[ -n "${model_id}" ]] && flags+=(--large="${model_id}")
+                [[ -n "${model_id}" ]] && flags+=(--medium="${model_id}")
 
             elif [[ "${group}" == "Light (Haiku)" ]]; then
                 local model_name
@@ -245,8 +262,10 @@ _synu_agent_claude_interactive() {
 
                 # Expand group flags to individual slots
                 case "${key}" in
-                    large)
+                    heavy)
                         _synu_cache_set claude opus "${value}"
+                        ;;
+                    medium)
                         _synu_cache_set claude sonnet "${value}"
                         _synu_cache_set claude agent "${value}"
                         ;;