@dst-justin/relay 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +5 -0
  2. package/package.json +1 -1
  3. package/relay +97 -44
package/README.md CHANGED
@@ -288,6 +288,11 @@ Sessions live in `~/.claude/projects/` and are shared across all accounts — af
288
288
 
289
289
  ## Changelog
290
290
 
291
+ ### v2.5.0 — 2026-08-12
292
+ - Add `--subagent-model` to `relay provider add`, storing a `subagent_model` field that `relay provider use`/`relay run` inject as `CLAUDE_CODE_SUBAGENT_MODEL` — lets a LiteLLM provider pin the subagent model independently of the main `ANTHROPIC_MODEL`.
293
+ - `relay provider list` now also shows `subagent_model` when set.
294
+ - Expand `relay help` with every subcommand's flags (provider add's `--base-url`/`--token`/`--model`/`--subagent-model`/`--discover-models`, `list -f`/`--no-usage`, `run -- <args>`, `warmup test`, aliases, etc.)
295
+
291
296
  ### v2.4.0 — 2026-07-25
292
297
  - Add LiteLLM provider support: `relay provider add/list/use/off/remove` routes Claude Code through a LiteLLM proxy instead of a subscription account, via `${CLAUDE_DIR}/settings.json`'s env block (never touches Keychain/credentials).
293
298
  - Add `relay run <name>` for a one-off session pinned to a specific account or provider, independent of any global switch.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dst-justin/relay",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "Multi-account switcher for Claude Code — instant credential swap across macOS, Linux, and Windows",
5
5
  "bin": {
6
6
  "relay": "./relay.js"
package/relay CHANGED
@@ -304,7 +304,7 @@ _settings_env_activate_locked() {
304
304
  "${PY}" <<'EOF'
305
305
  import json, os, sys, tempfile
306
306
 
307
- MANAGED = ["ANTHROPIC_BASE_URL", "ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_MODEL", "CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY"]
307
+ MANAGED = ["ANTHROPIC_BASE_URL", "ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_MODEL", "CLAUDE_CODE_SUBAGENT_MODEL", "CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY"]
308
308
 
309
309
  def load_json(p, default):
310
310
  if not os.path.exists(p):
@@ -367,7 +367,7 @@ _settings_env_restore_locked() {
367
367
  "${PY}" - "${CLAUDE_SETTINGS}" "${SETTINGS_ENV_SNAPSHOT}" <<'EOF'
368
368
  import json, os, sys, tempfile
369
369
 
370
- MANAGED = ["ANTHROPIC_BASE_URL", "ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_MODEL", "CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY"]
370
+ MANAGED = ["ANTHROPIC_BASE_URL", "ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_MODEL", "CLAUDE_CODE_SUBAGENT_MODEL", "CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY"]
371
371
 
372
372
  def load_json(p, default):
373
373
  if not os.path.exists(p):
@@ -966,7 +966,7 @@ PYEOF
966
966
 
967
967
  cmd_provider_add() {
968
968
  local name="${1:-}"
969
- [[ -z "${name}" ]] && { err "usage: relay provider add <name> --base-url <url> --token <token> [--model <model>] [--discover-models]"; exit 1; }
969
+ [[ -z "${name}" ]] && { err "usage: relay provider add <name> --base-url <url> --token <token> [--model <model>] [--subagent-model <model>] [--discover-models]"; exit 1; }
970
970
  shift
971
971
  case "${name}" in
972
972
  *[!a-zA-Z0-9_-]*) err "name must contain only letters, numbers, underscores, or hyphens"; exit 1 ;;
@@ -981,12 +981,13 @@ cmd_provider_add() {
981
981
  return 0
982
982
  fi
983
983
 
984
- local base_url="" token="" model="" discover=0
984
+ local base_url="" token="" model="" subagent_model="" discover=0
985
985
  while [[ $# -gt 0 ]]; do
986
986
  case "$1" in
987
987
  --base-url) base_url="${2:-}"; shift 2 ;;
988
988
  --token) token="${2:-}"; shift 2 ;;
989
989
  --model) model="${2:-}"; shift 2 ;;
990
+ --subagent-model) subagent_model="${2:-}"; shift 2 ;;
990
991
  --discover-models) discover=1; shift ;;
991
992
  *) err "unknown option: $1"; exit 1 ;;
992
993
  esac
@@ -1003,6 +1004,7 @@ cmd_provider_add() {
1003
1004
  RELAY_PROVIDER_BASE_URL="${base_url}" \
1004
1005
  RELAY_PROVIDER_TOKEN="${token}" \
1005
1006
  RELAY_PROVIDER_MODEL="${model}" \
1007
+ RELAY_PROVIDER_SUBAGENT_MODEL="${subagent_model}" \
1006
1008
  RELAY_PROVIDER_DISCOVER="${discover}" \
1007
1009
  "${PY}" -c '
1008
1010
  import json, os
@@ -1010,10 +1012,13 @@ path = os.environ["RELAY_PROVIDER_PATH"]
1010
1012
  base_url = os.environ["RELAY_PROVIDER_BASE_URL"]
1011
1013
  token = os.environ["RELAY_PROVIDER_TOKEN"]
1012
1014
  model = os.environ.get("RELAY_PROVIDER_MODEL", "")
1015
+ subagent_model = os.environ.get("RELAY_PROVIDER_SUBAGENT_MODEL", "")
1013
1016
  discover = os.environ.get("RELAY_PROVIDER_DISCOVER", "")
1014
1017
  d = {"base_url": base_url, "auth_token": token}
1015
1018
  if model:
1016
1019
  d["model"] = model
1020
+ if subagent_model:
1021
+ d["subagent_model"] = subagent_model
1017
1022
  if discover == "1":
1018
1023
  d["discover_models"] = True
1019
1024
  with open(path, "w") as f:
@@ -1032,13 +1037,15 @@ cmd_provider_list() {
1032
1037
  return 0
1033
1038
  fi
1034
1039
  local active; active=$(active_provider_name)
1035
- local name base_url model info
1040
+ local name base_url model subagent_model info
1036
1041
  while IFS= read -r name; do
1037
1042
  [[ -z "${name}" ]] && continue
1038
1043
  base_url=$(_provider_field "${name}" base_url)
1039
1044
  model=$(_provider_field "${name}" model)
1045
+ subagent_model=$(_provider_field "${name}" subagent_model)
1040
1046
  info="${base_url}"
1041
1047
  [[ -n "${model}" ]] && info="${info} model=${model}"
1048
+ [[ -n "${subagent_model}" ]] && info="${info} subagent_model=${subagent_model}"
1042
1049
  if [[ "${name}" == "${active}" ]]; then
1043
1050
  printf " ${GR}${B}✓ %-16s${R} ${D}%s${R}\n" "${name}" "${info}"
1044
1051
  else
@@ -1052,14 +1059,16 @@ cmd_provider_use() {
1052
1059
  [[ -z "${name}" ]] && { err "usage: relay provider use <name>"; exit 1; }
1053
1060
  provider_exists "${name}" || { err "Provider '${name}' not found"; exit 1; }
1054
1061
 
1055
- local base_url token model discover
1062
+ local base_url token model subagent_model discover
1056
1063
  base_url=$(_provider_field "${name}" base_url)
1057
1064
  token=$(_provider_field "${name}" auth_token)
1058
1065
  model=$(_provider_field "${name}" model)
1066
+ subagent_model=$(_provider_field "${name}" subagent_model)
1059
1067
  discover=$(_provider_discover "${name}")
1060
1068
 
1061
1069
  local pairs=("ANTHROPIC_BASE_URL=${base_url}" "ANTHROPIC_AUTH_TOKEN=${token}")
1062
1070
  [[ -n "${model}" ]] && pairs+=("ANTHROPIC_MODEL=${model}")
1071
+ [[ -n "${subagent_model}" ]] && pairs+=("CLAUDE_CODE_SUBAGENT_MODEL=${subagent_model}")
1063
1072
  [[ -n "${discover}" ]] && pairs+=("CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1")
1064
1073
 
1065
1074
  _settings_env_activate "${pairs[@]}" || { err "Failed to update ${CLAUDE_SETTINGS}"; exit 1; }
@@ -1106,10 +1115,11 @@ cmd_run() {
1106
1115
  do_switch "${name}"
1107
1116
  exec "${REAL_CLAUDE}" "$@"
1108
1117
  elif provider_exists "${name}"; then
1109
- local base_url token model discover settings_file
1118
+ local base_url token model subagent_model discover settings_file
1110
1119
  base_url=$(_provider_field "${name}" base_url)
1111
1120
  token=$(_provider_field "${name}" auth_token)
1112
1121
  model=$(_provider_field "${name}" model)
1122
+ subagent_model=$(_provider_field "${name}" subagent_model)
1113
1123
  discover=$(_provider_discover "${name}")
1114
1124
 
1115
1125
  # Opportunistic cleanup: a prior `relay run <provider>` can't clean up
@@ -1127,6 +1137,7 @@ cmd_run() {
1127
1137
  RELAY_RUN_BASE_URL="${base_url}" \
1128
1138
  RELAY_RUN_TOKEN="${token}" \
1129
1139
  RELAY_RUN_MODEL="${model}" \
1140
+ RELAY_RUN_SUBAGENT_MODEL="${subagent_model}" \
1130
1141
  RELAY_RUN_DISCOVER="${discover}" \
1131
1142
  RELAY_RUN_SETTINGS_FILE="${settings_file}" \
1132
1143
  "${PY}" -c '
@@ -1134,10 +1145,13 @@ import json, os
1134
1145
  base_url = os.environ["RELAY_RUN_BASE_URL"]
1135
1146
  token = os.environ["RELAY_RUN_TOKEN"]
1136
1147
  model = os.environ.get("RELAY_RUN_MODEL", "")
1148
+ subagent_model = os.environ.get("RELAY_RUN_SUBAGENT_MODEL", "")
1137
1149
  discover = os.environ.get("RELAY_RUN_DISCOVER", "")
1138
1150
  env = {"ANTHROPIC_BASE_URL": base_url, "ANTHROPIC_AUTH_TOKEN": token}
1139
1151
  if model:
1140
1152
  env["ANTHROPIC_MODEL"] = model
1153
+ if subagent_model:
1154
+ env["CLAUDE_CODE_SUBAGENT_MODEL"] = subagent_model
1141
1155
  if discover == "1":
1142
1156
  env["CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY"] = "1"
1143
1157
  with open(os.environ["RELAY_RUN_SETTINGS_FILE"], "w") as f:
@@ -2723,52 +2737,91 @@ cmd_uninstall() {
2723
2737
 
2724
2738
  cmd_help() {
2725
2739
  printf "\n${B}${CY} relay${R} ${D}%s — multi-account switcher for Claude Code${R}\n\n" "$(_read_version)"
2740
+
2726
2741
  printf " ${B}Inside Claude Code (prefix with !)${R}\n"
2727
- printf " %-32s %s\n" " !relay" "account menu + 5hr usage"
2728
- printf " %-32s %s\n" " !relay 2" "switch to account #2"
2729
- printf " %-32s %s\n" " !relay work" "switch to named account"
2730
- printf " %-32s %s\n" " !relay status" "detailed usage for current account"
2742
+ printf " %-42s %s\n" " !relay" "account menu + 5hr usage"
2743
+ printf " %-42s %s\n" " !relay 2" "switch to account #2 (by index shown in the menu)"
2744
+ printf " %-42s %s\n" " !relay work" "switch to account named 'work'"
2745
+ printf " %-42s %s\n" " !relay status" "detailed usage for current account"
2731
2746
  echo ""
2747
+
2732
2748
  printf " ${B}Account management${R}\n"
2733
- printf " %-32s %s\n" " relay add <name>" "add account via browser login"
2734
- printf " %-32s %s\n" " relay add-force <name>" "force re-login for existing account"
2735
- printf " %-32s %s\n" " relay refresh <name>" "re-login to refresh an expired token"
2736
- printf " %-32s %s\n" " relay refresh-all" "silent OAuth refresh for all accounts"
2737
- printf " %-32s %s\n" " relay save <name>" "save current login state"
2738
- printf " %-32s %s\n" " relay rename <old> <new>" "rename an account"
2739
- printf " %-32s %s\n" " relay reorder" "change account display/switch order"
2740
- printf " %-32s %s\n" " relay run <name>" "one-off session on an account or provider"
2741
- printf " %-32s %s\n" " relay list" "full list with weekly usage"
2742
- printf " %-32s %s\n" " relay list -f" "live-refresh mode (Ctrl+C to exit)"
2743
- printf " %-32s %s\n" " relay list --no-usage" "list without querying API"
2744
- printf " %-32s %s\n" " relay status -f" "live-refresh current account status"
2745
- printf " %-32s %s\n" " relay remove <name>" "delete an account"
2746
- printf " %-32s %s\n" " relay sessions" "show all sessions"
2747
- printf " %-32s %s\n" " relay version" "show current version"
2748
- printf " %-32s %s\n" " relay update" "update to latest version"
2749
- printf " %-32s %s\n" " relay uninstall" "remove relay and all account data"
2749
+ printf " %-42s %s\n" " relay add <name>" "add account via browser login (opens claude /login)"
2750
+ printf " %-42s %s\n" " relay add-force <name>" "wipe stored creds/meta first, then force re-login"
2751
+ printf " %-42s %s\n" " relay refresh <name>" "re-login to refresh an expired/expiring token"
2752
+ printf " %-42s %s\n" " relay refresh-all" "silent OAuth refresh for every stored account"
2753
+ printf " %-42s %s\n" " relay save <name>" "save whatever is currently logged in as <name>"
2754
+ printf " %-42s %s\n" " relay rename <old> <new>" "rename an account (updates order + current pointer)"
2755
+ printf " %-42s %s\n" " relay remove <name>" "delete an account (alias: rm, del)"
2756
+ printf " %-42s %s\n" " relay reorder" "interactively change account display/switch order"
2757
+ printf " %-42s %s\n" " relay switch <name|#>" "switch account by name or index (alias: sw, use)"
2758
+ printf " %-42s %s\n" " relay <name>" "bare name/index also switches (shortcut for switch)"
2759
+ printf " %-42s %s\n" " relay continue [name]" "optionally switch, then exec 'claude --continue' (alias: cont, c)"
2750
2760
  echo ""
2751
- printf " ${B}Autoswitch${R}\n"
2752
- printf " %-32s %s\n" " relay autoswitch config" "set up auto-switching"
2753
- printf " %-32s %s\n" " relay autoswitch start/stop" "manage background daemon"
2754
- printf " %-32s %s\n" " relay autoswitch status" "daemon state + thresholds"
2761
+
2762
+ printf " ${B}Listing & status${R}\n"
2763
+ printf " %-42s %s\n" " relay list" "full account list with weekly usage (alias: ls)"
2764
+ printf " %-42s %s\n" " -f, --follow" "live-refresh mode, redraws every 30s (Ctrl+C to exit)"
2765
+ printf " %-42s %s\n" " --no-usage" "list without querying the usage API (fast, offline)"
2766
+ printf " %-42s %s\n" " relay status" "detailed usage for the current account (alias: st)"
2767
+ printf " %-42s %s\n" " -f" "live-refresh current account status"
2768
+ printf " %-42s %s\n" " relay sessions" "show all local Claude sessions (alias: sess)"
2755
2769
  echo ""
2770
+
2771
+ printf " ${B}One-off runs${R}\n"
2772
+ printf " %-42s %s\n" " relay run <name>" "one-off session on an account or provider, then exec claude"
2773
+ printf " %-42s %s\n" " relay run <name> -- <args>" "forward extra args to claude itself, e.g. -- --resume"
2774
+ printf " %-42s %s\n" " (leaves global switch/provider state untouched — safe for concurrent sessions)"
2775
+ echo ""
2776
+
2756
2777
  printf " ${B}LiteLLM providers${R}\n"
2757
- printf " %-32s %s\n" " relay provider add <name> --base-url <url> --token <token>" "add a provider"
2758
- printf " %-32s %s\n" " relay provider list" "list configured providers"
2759
- printf " %-32s %s\n" " relay provider use <name>" "route all future sessions through this provider"
2760
- printf " %-32s %s\n" " relay provider off" "stop routing through a provider, resume subscription"
2761
- printf " %-32s %s\n" " relay provider remove <name>" "delete a provider"
2778
+ printf " %-42s %s\n" " relay provider add <name>" "add a LiteLLM-compatible provider (alias: prov)"
2779
+ printf " %-42s %s\n" " --base-url <url>" "required: http(s):// base URL of the gateway"
2780
+ printf " %-42s %s\n" " --token <token>" "required: auth token/API key for the gateway"
2781
+ printf " %-42s %s\n" " --model <model>" "optional: pin ANTHROPIC_MODEL to this alias"
2782
+ printf " %-42s %s\n" " --subagent-model <model>" "optional: pin CLAUDE_CODE_SUBAGENT_MODEL"
2783
+ printf " %-42s %s\n" " " "(overrides every subagent's own model: frontmatter)"
2784
+ printf " %-42s %s\n" " --discover-models" "optional: enable gateway model discovery instead of pinning"
2785
+ printf " %-42s %s\n" " relay provider list" "list configured providers + their settings"
2786
+ printf " %-42s %s\n" " relay provider use <name>" "route all future sessions through this provider"
2787
+ printf " %-42s %s\n" " relay provider off" "stop routing through a provider, resume subscription account"
2788
+ printf " %-42s %s\n" " relay provider remove <name>" "delete a provider (prompts for confirmation)"
2789
+ echo ""
2790
+
2791
+ printf " ${B}Autoswitch daemon${R}\n"
2792
+ printf " %-42s %s\n" " relay autoswitch config" "interactive setup: order, thresholds, poll interval (alias: as)"
2793
+ printf " %-42s %s\n" " relay autoswitch start" "install + start the background launchd/systemd daemon"
2794
+ printf " %-42s %s\n" " relay autoswitch stop" "stop and uninstall the background daemon"
2795
+ printf " %-42s %s\n" " relay autoswitch status" "daemon running state + per-account thresholds"
2796
+ printf " %-42s %s\n" " relay autoswitch log" "tail the daemon's log file"
2797
+ printf " %-42s %s\n" " relay autoswitch" "no subcommand: config if unset, else status"
2798
+ echo ""
2799
+
2800
+ printf " ${B}Locking (autoswitch)${R}\n"
2801
+ printf " %-42s %s\n" " relay lock <name>" "exclude an account from autoswitch cycling when over limit"
2802
+ printf " %-42s %s\n" " relay unlock <name>" "remove a lock"
2803
+ printf " %-42s %s\n" " relay lock" "no argument: show all locked accounts"
2762
2804
  echo ""
2805
+
2763
2806
  printf " ${B}Warmup${R}\n"
2764
- printf " %-32s %s\n" " relay warmup add <acct> <HH:MM>" "pre-warm an account's 5hr window daily"
2765
- printf " %-32s %s\n" " relay warmup remove <acct> [HH:MM]" "remove a warmup schedule"
2766
- printf " %-32s %s\n" " relay warmup list" "show scheduled warmups + last result"
2767
- printf " %-32s %s\n" " relay warmup pause/resume" "suspend/re-enable without deleting"
2768
- printf " %-32s %s\n" " relay lock <name>" "prevent account from cycling back when over limit"
2769
- printf " %-32s %s\n" " relay unlock <name>" "remove lock"
2770
- printf " %-32s %s\n" " relay lock" "show locked accounts"
2807
+ printf " %-42s %s\n" " relay warmup add <acct> <HH:MM>" "schedule a daily pre-warm ping (24h local time)"
2808
+ printf " %-42s %s\n" " relay warmup remove <acct> [HH:MM]" "remove one scheduled time, or all for <acct> if omitted (alias: rm)"
2809
+ printf " %-42s %s\n" " relay warmup list" "show scheduled warmups + last-run result (alias: ls)"
2810
+ printf " %-42s %s\n" " relay warmup test <acct>" "fire a warmup ping for <acct> right now, synchronously"
2811
+ printf " %-42s %s\n" " relay warmup pause" "suspend all warmups without deleting entries"
2812
+ printf " %-42s %s\n" " relay warmup resume" "re-enable previously paused warmups"
2813
+ printf " %-42s %s\n" " relay warmup" "no subcommand: same as 'relay warmup list'"
2814
+ printf " %-42s %s\n" " requires the autoswitch daemon running (relay autoswitch start) to actually fire"
2771
2815
  echo ""
2816
+
2817
+ printf " ${B}Maintenance${R}\n"
2818
+ printf " %-42s %s\n" " relay version" "show current version (alias: --version, -V)"
2819
+ printf " %-42s %s\n" " relay update" "update relay to latest version"
2820
+ printf " %-42s %s\n" " relay install" "(re)install shell integration / launcher"
2821
+ printf " %-42s %s\n" " relay uninstall" "remove relay and all account data"
2822
+ printf " %-42s %s\n" " relay help" "show this help (alias: --help, -h)"
2823
+ echo ""
2824
+
2772
2825
  printf " ${D}switches the OAuth credential (macOS Keychain / Linux ~/.claude/.credentials.json); sessions are shared${R}\n"
2773
2826
  printf " ${D}after switching: claude -c to resume, claude --resume <id> for a specific session${R}\n\n"
2774
2827
  _check_update_bg