cd /news/developer-tools/synthetic-claude-code-wrapper-defaul… · home topics developer-tools article
[ARTICLE · art-76272] src=gist.github.com ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Synthetic Claude Code wrapper (defaults to K3 as the model)

A developer created a shell wrapper called 'synclaude' that routes Claude Code's interface through Synthetic's API, allowing users to run open models like Kimi K3, GLM 5.2, and MiniMax M3 while keeping Claude Code's agent and tool features. The wrapper validates models against Synthetic's live catalogue and ensures all model slots use the chosen model.

read8 min views1 publishedJul 28, 2026

A shell wrapper that points Claude Code at Synthetic, so you keep the Claude Code interface — agents, tools, subagents, slash commands — while inference runs on open models like Kimi K3, GLM 5.2 and MiniMax M3.

It is one function plus three helpers. Paste the block below into your shell rc and you are done.

  • Picks a model per run with a substring: --model k3

,--model glm-5.2

  • Validates the model against Synthetic's live catalogue, so a typo fails immediately with the real options instead of silently doing the wrong thing
  • Points every model slot at your choice — main, opus, sonnet, haikuand subagents— so delegated work does not quietly fall back to something else - Leaks nothing into your shell: every variable is scoped to the child process
Tool Why
claude
the CLI itself — npm i -g @anthropic-ai/claude-code
curl
fetches the model catalogue
jq
parses it — brew install jq
awk , sed , find
matching and caching (already on macOS/Linux)

Shell: bash 3.2+ or zsh. It uses arrays, so it is not POSIX sh

.

A Synthetic API key: https://synthetic.newSettings → API Keys.

Add your key and the function to ~/.zshrc

(or ~/.bashrc

):

export SYNTHETIC_API_KEY="syn_xxxxxxxxxxxxxxxx"

Then paste this block:


_synclaude_models() {
  local cache="${TMPDIR:-/tmp}/synclaude-models-$(id -u).json"

  if [ -n "${1:-}" ] || [ ! -s "$cache" ] || [ -n "$(find "$cache" -mmin +360 2>/dev/null)" ]; then
    if curl -fsS -m 20 https://api.synthetic.new/v1/models \
         -H "Authorization: Bearer ${SYNTHETIC_API_KEY:-}" -o "$cache.tmp" 2>/dev/null; then
      mv -f "$cache.tmp" "$cache"
    else
      rm -f "$cache.tmp"
      [ -s "$cache" ] || return 1
    fi
  fi

  jq -r '.data[]?.id' "$cache" 2>/dev/null | sort
}

#
#
_synclaude_resolve_model() {
  local query="$1" ids matches

  if ! command -v jq >/dev/null 2>&1; then
    printf >&2 "synclaude: --model needs 'jq' to read the catalogue (brew install jq)\n"
    return 1
  fi

  if ! ids="$(_synclaude_models)"; then
    printf >&2 'synclaude: could not fetch the catalogue from api.synthetic.new\n'
    return 1
  fi

  if [ "$query" = "--list" ]; then
    printf '%s\n' "$ids"
    return 0
  fi

  matches="$(printf '%s\n' "$ids" | awk -v q="$query" '$0 == q')"
  [ -z "$matches" ] && matches="$(printf '%s\n' "$ids" |
    awk -v q="$query" 'BEGIN{q=tolower(q)} index(tolower($0), q)')"

  if [ -z "$matches" ]; then
    ids="$(_synclaude_models force)" || :
    matches="$(printf '%s\n' "$ids" |
      awk -v q="$query" 'BEGIN{q=tolower(q)} index(tolower($0), q)')"
  fi

  if [ -z "$matches" ]; then
    printf >&2 "synclaude: no model matches '%s'. Available:\n" "$query"
    printf '%s\n' "$ids" | sed 's/^/  /' >&2
    return 1
  fi

  if [ "$(printf '%s\n' "$matches" | awk 'END{print NR}')" -gt 1 ]; then
    printf >&2 "synclaude: '%s' is ambiguous, it matches:\n" "$query"
    printf '%s\n' "$matches" | sed 's/^/  /' >&2
    return 1
  fi

  printf '%s\n' "$matches"
}

_synclaude_help() {
  cat <<HELP
synclaude - Claude Code against Synthetic

Usage:
  synclaude [--model <id|substring>] [--thinking|--no-thinking] [claude args ...]
  synclaude --help

Options:
  --model <m>    Override every model for this run - main, opus, sonnet, haiku
                 and subagent all become <m>. Takes a full model id or any
                 case-insensitive substring that matches exactly one.
  --no-thinking  Turn extended thinking off (the default here, see below).
  --thinking     Turn extended thinking back on.
  -h, --help     Show this message. Claude's own help is 'claude --help'.

Everything else is passed to claude untouched.

Current configuration:
  credential   SYNTHETIC_API_KEY
  endpoint     ${SYNTHETIC_BASE_URL:-https://api.synthetic.new/anthropic}
  model        ${SYNTHETIC_MODEL:-hf:moonshotai/Kimi-K3}
  thinking     ${SYNTHETIC_THINKING:-off}
HELP

  printf '\nAvailable models:\n'
  _synclaude_resolve_model --list 2>/dev/null | sed 's/^/  /'
}

synclaude() {
  local model="${SYNTHETIC_MODEL:-hf:moonshotai/Kimi-K3}"
  local base_url="${SYNTHETIC_BASE_URL:-https://api.synthetic.new/anthropic}"
  local thinking="${SYNTHETIC_THINKING:-off}"
  local requested_model=""
  local -a args
  args=()

  while [ $# -gt 0 ]; do
    case "$1" in
      -h|--help)      _synclaude_help; return 0 ;;
      --no-thinking)  thinking=off; shift ;;
      --thinking)     thinking=on; shift ;;
      --model)
        if [ -z "${2:-}" ]; then
          printf >&2 'synclaude: --model needs a value (try: synclaude --help)\n'
          return 2
        fi
        requested_model="$2"; shift 2 ;;
      --model=*)      requested_model="${1#--model=}"; shift ;;
      *)              args+=("$1"); shift ;;
    esac
  done

  if [ -z "${SYNTHETIC_API_KEY:-}" ]; then
    printf >&2 'synclaude: SYNTHETIC_API_KEY is not set\n'
    return 1
  fi

  if ! command -v claude >/dev/null 2>&1; then
    printf >&2 "synclaude: 'claude' not found in PATH. Install: npm i -g @anthropic-ai/claude-code\n"
    return 127
  fi

  if [ -n "$requested_model" ]; then
    model="$(_synclaude_resolve_model "$requested_model")" || return 1
  fi

  local disable_thinking=1
  [ "$thinking" = "on" ] && disable_thinking=

  printf >&2 'synclaude: endpoint=%s | model=%s | thinking=%s\n' "$base_url" "$model" "$thinking"

  env \
    ANTHROPIC_BASE_URL="$base_url" \
    ANTHROPIC_AUTH_TOKEN="$SYNTHETIC_API_KEY" \
    ANTHROPIC_API_KEY= \
    ANTHROPIC_MODEL="$model" \
    ANTHROPIC_DEFAULT_OPUS_MODEL="$model" \
    ANTHROPIC_DEFAULT_SONNET_MODEL="$model" \
    ANTHROPIC_DEFAULT_HAIKU_MODEL="$model" \
    CLAUDE_CODE_SUBAGENT_MODEL="$model" \
    CLAUDE_CODE_DISABLE_THINKING="$disable_thinking" \
    CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
    CLAUDE_CODE_ATTRIBUTION_HEADER=0 \
    CLAUDE_CODE_MAX_OUTPUT_TOKENS="${CLAUDE_CODE_MAX_OUTPUT_TOKENS:-32000}" \
    MAX_THINKING_TOKENS="${MAX_THINKING_TOKENS:-100000}" \
    IS_DEMO="${IS_DEMO-true}" \
    claude ${args[@]+"${args[@]}"}
}

Reload with exec $SHELL -l

, then run synclaude --help

.

synclaude                                   # interactive, default model
synclaude -p "explain this repo"            # one-shot
synclaude --model glm-5.2 --thinking        # switch model, thinking on
synclaude --model k2.7                      # substring is enough
synclaude --help                            # options + live model list

--model

accepts any case-insensitive substring that matches exactly one catalogue entry. Everything the wrapper does not recognise is forwarded to claude

untouched, so --resume

, --output-format json

, --verbose

and the rest all work as usual.

$ synclaude --model glm
synclaude: 'glm' is ambiguous, it matches:
  hf:zai-org/GLM-4.7-Flash
  hf:zai-org/GLM-5.2

Thinking is off by default, and that is not an arbitrary choice.

Claude Code sends a reasoning effort of medium

to third-party models. Some models do not accept that value. Kimi K3 advertises only ['high','low','max']

, so with thinking on every request fails:

API Error: 500 {"error":"Error from inference backend: 500
Unsupported thinking_effort='medium'; supported values are ['high','low','max']."}

There is currently no way to change the value Claude Code sends. --effort

(its own CLI flag), CLAUDE_CODE_EFFORT_LEVEL

, CLAUDE_CODE_ALWAYS_ENABLE_EFFORT

and CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING

were each tested against this endpoint and the error came back identical, still naming medium

. Synthetic's catalogue does not publish per-model effort levels either, so the wrapper cannot map them for you.

Turning thinking off avoids the rejected parameter entirely, which is why it is the default here. The trade-off is real: you lose extended reasoning. On a model that accepts medium

, turn it back on:

synclaude --model glm-5.2 --thinking

If you would rather default to a model that thinks, set SYNTHETIC_MODEL=hf:zai-org/GLM-5.2

and SYNTHETIC_THINKING=on

.

All optional except the key.

Variable Default Purpose
SYNTHETIC_API_KEY
Required. Your Synthetic key
SYNTHETIC_MODEL
hf:moonshotai/Kimi-K3
Default model
SYNTHETIC_THINKING
off
on to default extended thinking on
SYNTHETIC_BASE_URL
https://api.synthetic.new/anthropic
Endpoint
CLAUDE_CODE_MAX_OUTPUT_TOKENS
32000
Max output tokens
MAX_THINKING_TOKENS
100000
Thinking budget when thinking is on
IS_DEMO
true
Trims the startup banner. IS_DEMO= synclaude restores it

Two details worth knowing:

hides the "Tips for getting started" and "What's new" panels and your account/org line. Claude Code treatsIS_DEMO

any non-empty valueas on — including0

andfalse

— so the only way back to the full banner is an empty one:IS_DEMO= synclaude

.on every run so a real Anthropic key sitting in your environment cannot outrank the Synthetic token.ANTHROPIC_API_KEY

is blanked

** SYNTHETIC_API_KEY is not set** — export it, then reload your shell.

** no model matches '...'** — the error lists every available id. The catalogue is cached for six hours; to force a refresh:

rm -f "${TMPDIR:-/tmp}/synclaude-models-$(id -u).json"

** Unsupported thinking_effort='medium'** — that model rejects the effort level Claude Code sends. Drop

--thinking

, or pick another model.Model ids change. Synthetic rotates them without notice — Kimi-K2.5

was a working default until it began returning 404. That is exactly why this wrapper reads the catalogue from the API rather than hardcoding a list. Run synclaude --help

to see what is live right now.

Tested on macOS with Claude Code 2.1.220 in both bash

and zsh

— including pristine shells with no rc files — covering the default model, --model

overrides, ambiguous and unknown input, missing key and missing binary, and live end-to-end runs against the real API on Kimi K3 and GLM 5.2.

Public domain / CC0. Use it however you like.

── more in #developer-tools 4 stories · sorted by recency
── more on @claude code 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/synthetic-claude-cod…] indexed:0 read:8min 2026-07-28 ·