1 line
288 KiB
JSON
1 line
288 KiB
JSON
{"repo": "agents365-ai/dsclaude", "files": {"mmclaude": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785595132.83843, "n": 4454, "h": "19167c0f60f9c088", "c": "#!/usr/bin/env bash\n# shellcheck disable=SC2034 # variables consumed by lib/common.sh\n# mmclaude — launch Claude Code on Xiaomi MiMo's Anthropic-compatible API.\n#\n# Follows the official MiMo \"Claude Code 配置\" guide:\n# - Pay-as-you-go : https://api.xiaomimimo.com/anthropic (sk-... keys)\n# - Token Plan : https://token-plan-cn.xiaomimimo.com/anthropic (tp-... keys)\n# (Token Plan subscribers may receive a custom subdomain — override\n# the base URL via MIMO_BASE_URL.)\n#\n# Reads MIMO_API_KEY from the environment first, then falls back to\n# ~/.zshrc / ~/.bashrc / ~/.bash_profile / ~/.profile if not already exported.\n#\n# Quick start (no install needed):\n# chmod +x mmclaude\n# ./mmclaude\n#\n# Optional — make it globally available:\n# sudo mv mmclaude /usr/local/bin/ && sudo chmod +x /usr/local/bin/mmclaude\n#\n# Use:\n# mmclaude # start on mimo-v2.5-pro (MiMo default)\n# mmclaude fast # start on mimo-v2.5 (cheaper / faster flash tier)\n# mmclaude long # request max context window\n# mmclaude effort max # set reasoning effort (low|medium|high|xhigh|max)\n# mmclaude update # git pull latest from this repo\n# mmclaude --help # any remaining flag is forwarded to claude\n#\n# Optional env overrides:\n# MIMO_MODEL=mimo-v2.5-pro # main model\n# MIMO_FLASH_MODEL=mimo-v2.5 # flash / haiku / subagent tier\n# MIMO_BASE_URL=https://.../anthropic # custom Anthropic-compatible base URL\n# MIMO_CTX=1048576 # max context tokens (defaults to 1M with `long`)\n# MIMO_OUTPUT=8000 # cap output tokens\n# MIMO_EFFORT=max # CLAUDE_CODE_EFFORT_LEVEL\n#\n# In-session switch:\n# /model mimo-v2.5 # switch to the flash tier\n# /model mimo-v2.5-pro # switch back to pro\n#\nset -euo pipefail\n\n# Resolve symlink to find the real script directory.\n_SELF=\"$0\"\nif [ -L \"$_SELF\" ]; then\n _LINK=\"$(readlink \"$_SELF\")\"\n case \"$_LINK\" in\n /*) _SELF=\"$_LINK\" ;;\n *) _SELF=\"$(cd \"$(dirname \"$_SELF\")\" && pwd)/$_LINK\" ;;\n esac\nfi\nSELF_DIR=\"$(cd \"$(dirname \"$_SELF\")\" && pwd)\"\nif [ -f \"$SELF_DIR/lib/common.sh\" ]; then source \"$SELF_DIR/lib/common.sh\"\nelif [ -f \"$SELF_DIR/../lib/common.sh\" ]; then source \"$SELF_DIR/../lib/common.sh\"\nelse echo \"mmclaude: cannot find lib/common.sh. Reinstall or cd to repo.\" >&2; exit 1; fi\n\ncheck_version \"mmclaude\" \"$@\"\n\nPRO_MODEL=\"${MIMO_MODEL:-mimo-v2.5-pro}\"\nFLASH_MODEL=\"${MIMO_FLASH_MODEL:-mimo-v2.5}\"\n\n# Handle the update subcommand before the API-key check so it works key-less.\nif [ $# -gt 0 ] && [ \"$1\" = \"update\" ]; then\n do_update \"mmclaude\" \"MMCLAUDE_HOME\"\nfi\n\nAPI_KEY=\"$(resolve_api_key \"MIMO_API_KEY\")\"\nif [ -z \"$API_KEY\" ]; then\n echo \"❌ MIMO_API_KEY not found.\" >&2\n echo \" Add one line to ~/.zshrc or ~/.bashrc:\" >&2\n echo \" export MIMO_API_KEY=sk-xxxxxxxxxxxxxxxxxx # pay-as-you-go\" >&2\n echo \" export MIMO_API_KEY=tp-xxxxxxxxxxxxxxxxxx # Token Plan\" >&2\n exit 1\nfi\n\n# Auto-detect the base URL from the key prefix; MIMO_BASE_URL env always wins.\nBASE_URL=\"${MIMO_BASE_URL:-}\"\nif [ -z \"$BASE_URL\" ]; then\n case \"$API_KEY\" in\n tp-*) BASE_URL=\"https://token-plan-cn.xiaomimimo.com/anthropic\" ;;\n *) BASE_URL=\"https://api.xiaomimimo.com/anthropic\" ;;\n esac\nfi\n\nLONG_CTX=0\nEFFORT=\"${MIMO_EFFORT:-}\"\n\n# Positional alias: `fast`/`flash` runs the flash tier as the main model.\nMAIN_MODEL=\"$PRO_MODEL\"\nwhile [ $# -gt 0 ]; do\n case \"$1\" in\n fast|flash) MAIN_MODEL=\"$FLASH_MODEL\"; shift ;;\n long) LONG_CTX=1; shift ;;\n effort)\n case \"${2:-}\" in\n low|medium|high|xhigh|max) EFFORT=\"$2\"; shift 2 ;;\n *) echo \"mmclaude: invalid effort level '${2:-}'. Use: low medium high xhigh max\" >&2; exit 1 ;;\n esac\n ;;\n --) shift; break ;;\n *) break ;;\n esac\ndone\n\n# Surface the other model in Claude Code's /model picker for mid-session switching.\nif [ \"$MAIN_MODEL\" = \"$PRO_MODEL\" ]; then\n OTHER_MODEL=\"$FLASH_MODEL\"\n OTHER_DESC=\"MiMo v2.5 — fast / cheap haiku tier\"\nelse\n OTHER_MODEL=\"$PRO_MODEL\"\n OTHER_DESC=\"MiMo v2.5 Pro — full reasoning\"\nfi\n\nexport_anthropic_base\n# Subagents run on the cheaper flash tier.\nexport CLAUDE_CODE_SUBAGENT_MODEL=\"$FLASH_MODEL\"\nset_custom_model \"$OTHER_MODEL\" \"$MAIN_MODEL\" \"$OTHER_DESC\"\n\nCTX=\"${MIMO_CTX:-}\"\nOUTPUT_CAP=\"${MIMO_OUTPUT:-}\"\napply_context_and_effort\n\nshow_banner_and_launch \"MiMo\" \"$@\"\n"}}, "mmclaude.ps1": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785595140.657529, "n": 9815, "h": "3104e1025c7c8863", "c": "#!/usr/bin/env pwsh\n# mmclaude.ps1 — launch Claude Code on Xiaomi MiMo's Anthropic-compatible API (Windows port).\n#\n# Windows companion to the macOS/Linux bash script `mmclaude`. Same env vars,\n# same model picker — different shell.\n#\n# Follows the official MiMo \"Claude Code 配置\" guide:\n# - Pay-as-you-go : https://api.xiaomimimo.com/anthropic (sk-... keys)\n# - Token Plan : https://token-plan-cn.xiaomimimo.com/anthropic (tp-... keys)\n#\n# Reads MIMO_API_KEY from the process env first, then User/Machine env vars.\n# The base URL is auto-detected from the key prefix (tp-* → Token Plan, else\n# pay-as-you-go); override with $env:MIMO_BASE_URL.\n#\n# Quick start (from the mmclaude directory):\n# pwsh -File .\\mmclaude.ps1\n#\n# Three invocation rules that matter on Windows:\n# 1. Use `pwsh`, not `powershell`. PowerShell 5.1 ships with Windows but its\n# legacy console host breaks Ink-based CLIs (claude exits silently after\n# the first keystroke). This script refuses to run on PS < 7.\n# Install once: winget install Microsoft.PowerShell\n# 2. Use `-File`, not `-Command` / `&`. `-File` runs the script in a clean\n# arg-parsing mode; `-Command` re-tokenizes the line and mangles paths.\n# 3. Allow local scripts to run (one-time, current user only):\n# Set-ExecutionPolicy -Scope CurrentUser RemoteSigned\n#\n# Launching from a shortcut, Run dialog, or another shell:\n# Start-Process pwsh -ArgumentList '-NoExit', '-File',\n# 'C:\\Users\\<you>\\Desktop\\mmclaude\\mmclaude.ps1'\n# (`-NoExit` keeps the window open if the launching context doesn't have one.)\n#\n# Optional — make it globally available (one-time, from this dir):\n# $bin = \"$env:USERPROFILE\\bin\"; New-Item -ItemType Directory -Force $bin | Out-Null\n# Copy-Item .\\mmclaude.ps1 $bin\\mmclaude.ps1\n# # then add $bin to PATH and run: pwsh -File mmclaude.ps1\n#\n# Use:\n# pwsh -File ./mmclaude.ps1 # mimo-v2.5-pro (MiMo default)\n# pwsh -File ./mmclaude.ps1 fast # run the flash tier (mimo-v2.5) as main\n# pwsh -File ./mmclaude.ps1 long # request max context window\n# pwsh -File ./mmclaude.ps1 effort max # set effort (low|medium|high|xhigh|max)\n# pwsh -File ./mmclaude.ps1 update # git pull latest from this repo\n# pwsh -File ./mmclaude.ps1 --help # any remaining flag is forwarded to claude\n#\n# Optional env overrides (take precedence over positional aliases):\n# $env:MIMO_MODEL = 'mimo-v2.5-pro' # main model\n# $env:MIMO_FLASH_MODEL = 'mimo-v2.5' # flash / haiku / subagent tier\n# $env:MIMO_BASE_URL = 'https://.../anthropic' # custom base URL\n# $env:MIMO_CTX = '1048576' # max context tokens\n# $env:MIMO_OUTPUT = '8000' # cap output tokens\n# $env:MIMO_EFFORT = 'max' # CLAUDE_CODE_EFFORT_LEVEL\n#\n# In-session switch:\n# /model mimo-v2.5 # switch to the flash tier\n# /model mimo-v2.5-pro # switch back to the main model\n#\n# Requires: PowerShell 7+ (`winget install Microsoft.PowerShell`), Claude Code\n# CLI on PATH (`npm i -g @anthropic-ai/claude-code`), MiMo API key.\n\n[CmdletBinding()]\nparam(\n [Parameter(ValueFromRemainingArguments = $true)]\n [string[]]$Rest\n)\n\n$ErrorActionPreference = 'Stop'\n\n# ---- PowerShell version guard ----------------------------------------------\n# Windows PowerShell 5.1 ships with a legacy console host whose raw-mode TTY\n# breaks Ink (the React-for-CLI framework Claude Code uses): the welcome\n# screen renders, then the first keystroke causes claude to exit silently.\n# PowerShell 7+ uses ConPTY and works correctly. Refuse early with a clear\n# message rather than letting the user debug the silent-exit symptom.\nif ($PSVersionTable.PSVersion.Major -lt 7) {\n Write-Error @\"\nmmclaude.ps1: PowerShell 7+ required (you're on $($PSVersionTable.PSVersion)).\n\nWindows PowerShell 5.1 cannot host claude's interactive UI — the first\nkeystroke causes claude to exit. Install PowerShell 7 once:\n\n winget install Microsoft.PowerShell\n\nThen re-run with:\n\n pwsh -File .\\mmclaude.ps1\n\"@\n exit 1\n}\n\n# ---- Self-update -----------------------------------------------------------\n\nfunction Invoke-MmclaudeUpdate {\n $repo = $null\n $selfDir = Split-Path -Parent $PSCommandPath\n if (Test-Path (Join-Path $selfDir '.git')) {\n $repo = $selfDir\n }\n if (-not $repo -and $env:MMCLAUDE_HOME) {\n $repo = $env:MMCLAUDE_HOME\n }\n if (-not $repo) {\n $candidate = Join-Path $env:USERPROFILE 'github\\xxclaude'\n if (Test-Path (Join-Path $candidate '.git')) { $repo = $candidate }\n }\n if (-not $repo) {\n Write-Error @'\nmmclaude: cannot find the xxclaude repo for self-update.\n Set $env:MMCLAUDE_HOME = 'C:\\path\\to\\xxclaude' or cd into the repo and run pwsh -File ./mmclaude.ps1 update\n'@\n exit 1\n }\n Write-Host \"mmclaude: pulling latest from $repo ...\"\n git -C $repo pull\n if ($LASTEXITCODE -ne 0) {\n Write-Error 'mmclaude: git pull failed. Check network or resolve conflicts manually.'\n exit 1\n }\n Write-Host 'mmclaude: updated.'\n exit 0\n}\n\n# ---- API key resolution ----------------------------------------------------\n\nfunction Resolve-ApiKey {\n if ($env:MIMO_API_KEY) { return $env:MIMO_API_KEY }\n foreach ($scope in 'User', 'Machine') {\n $v = [Environment]::GetEnvironmentVariable('MIMO_API_KEY', $scope)\n if ($v) { return $v }\n }\n Write-Error @'\nMIMO_API_KEY not found.\n Set it persistently (User scope, takes effect in new shells):\n setx MIMO_API_KEY \"sk-xxxxxxxxxxxxxxxxxx\" # or tp-... for Token Plan\n Or for the current shell only:\n $env:MIMO_API_KEY = 'sk-xxxxxxxxxxxxxxxxxx'\n'@\n exit 1\n}\n\n# ---- Arg parsing -----------------------------------------------------------\n\n$WantFlash = $false\n$LongCtx = $false\n$Effort = if ($env:MIMO_EFFORT) { $env:MIMO_EFFORT } else { '' }\n\n$remaining = @()\n$rest = @($Rest)\n$i = 0\n:argloop while ($i -lt $rest.Count) {\n $a = $rest[$i]\n switch -CaseSensitive ($a) {\n 'update' { Invoke-MmclaudeUpdate }\n 'fast' { $WantFlash = $true; $i++; break }\n 'flash' { $WantFlash = $true; $i++; break }\n 'long' { $LongCtx = $true; $i++; break }\n 'effort' {\n $i++; if ($i -lt $rest.Count) { $l=$rest[$i]; if ($l -in 'low','medium','high','xhigh','max'){$Effort=$l;$i++;break}else{Write-Error \"mmclaude: invalid effort level '$l'. Use: low medium high xhigh max\";exit 1}}else{Write-Error \"mmclaude: 'effort' requires a level: low medium high xhigh max\";exit 1}\n }\n '--' {\n $i++\n if ($i -lt $rest.Count) { $remaining += $rest[$i..($rest.Count - 1)] }\n break argloop\n }\n default {\n $remaining += $rest[$i..($rest.Count - 1)]\n break argloop\n }\n }\n}\n\n$apiKey = Resolve-ApiKey\n\n# Auto-detect the base URL from the key prefix; MIMO_BASE_URL always wins.\n$baseUrl = if ($env:MIMO_BASE_URL) {\n $env:MIMO_BASE_URL\n} elseif ($apiKey -like 'tp-*') {\n 'https://token-plan-cn.xiaomimimo.com/anthropic'\n} else {\n 'https://api.xiaomimimo.com/anthropic'\n}\n\n$proModel = if ($env:MIMO_MODEL) { $env:MIMO_MODEL } else { 'mimo-v2.5-pro' }\n$flashModel = if ($env:MIMO_FLASH_MODEL) { $env:MIMO_FLASH_MODEL } else { 'mimo-v2.5' }\n\n$mainModel = if ($WantFlash) { $flashModel } else { $proModel }\n\n# Pick the \"other\" model to surface in Claude Code's /model picker.\nif ($mainModel -eq $proModel) {\n $otherModel = $flashModel\n $otherDesc = 'MiMo v2.5 — fast / cheap haiku tier'\n} else {\n $otherModel = $proModel\n $otherDesc = 'MiMo v2.5 Pro — full reasoning'\n}\n\n# ---- Export env for claude -------------------------------------------------\n\n# MiMo docs warn that lingering official Anthropic credentials shadow\n# ANTHROPIC_AUTH_TOKEN and make Claude Code hit api.anthropic.com instead.\n$env:ANTHROPIC_API_KEY = $null\n\n$env:ANTHROPIC_BASE_URL = $baseUrl\n$env:ANTHROPIC_AUTH_TOKEN = $apiKey\n$env:ANTHROPIC_MODEL = $mainModel\n$env:ANTHROPIC_DEFAULT_OPUS_MODEL = $mainModel\n$env:ANTHROPIC_DEFAULT_SONNET_MODEL = $mainModel\n$env:ANTHROPIC_DEFAULT_HAIKU_MODEL = $flashModel\n# Subagents run on the cheaper flash tier.\n$env:CLAUDE_CODE_SUBAGENT_MODEL = $flashModel\n\n# Expose the other MiMo model inside the /model picker (skip when identical).\nif ($otherModel -ne $mainModel) {\n $env:ANTHROPIC_CUSTOM_MODEL_OPTION = $otherModel\n $env:ANTHROPIC_CUSTOM_MODEL_OPTION_NAME = $otherModel\n $env:ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION = $otherDesc\n}\n\n# ---- Effort level ----------------------------------------------------------\nif ($Effort) { $env:CLAUDE_CODE_EFFORT_LEVEL = $Effort }\n# ---- Context window --------------------------------------------------------\n$ctx = if ($env:MIMO_CTX) { $env:MIMO_CTX } elseif ($LongCtx) { '1048576' } else { '' }\nif ($ctx) { $env:CLAUDE_CODE_MAX_CONTEXT_TOKENS = $ctx; $env:DISABLE_COMPACT = '1' }\n# ---- Output cap ------------------------------------------------------------\nif ($env:MIMO_OUTPUT) { $env:CLAUDE_CODE_MAX_OUTPUT_TOKENS = $env:MIMO_OUTPUT }\n\n# ---- Launch ----------------------------------------------------------------\n\nif (-not (Get-Command claude -ErrorAction SilentlyContinue)) {\n Write-Error @'\nmmclaude: `claude` CLI not found on PATH.\n Install Claude Code: npm install -g @anthropic-ai/claude-code\n Then re-run this script.\n'@\n exit 1\n}\n\n$banner = \"🚀 Claude Code on MiMo → $mainModel ($baseUrl)\"\nif ($ctx) { $banner += \" | ctx=$ctx\" }\nif ($Effort) { $banner += \" | effort=$Effort\" }\nif ($otherModel -ne $mainModel) { $banner += ' (switch mid-session via /model)' }\nWrite-Host $banner\n\n& claude @remaining\nexit $LASTEXITCODE\n"}}, "xclaude": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785595188.9795377, "n": 9065, "h": "d43238ea81783fad", "c": "#!/usr/bin/env bash\n# shellcheck disable=SC2034 # variables consumed by lib/common.sh\n# xclaude — auto-detect your API key and launch the right backend for Claude Code.\n#\n# Checks env vars and shell rc files for a known API key, then delegates to the\n# matching launcher. No need to remember which script name maps to which provider.\n#\n# Supported providers (checked in order):\n# DEEPSEEK_API_KEY → dsclaude (DeepSeek)\n# MIMO_API_KEY → mmclaude (Xiaomi MiMo)\n# DASHSCOPE_API_KEY → qwclaude (Bailian Qwen, pay-as-you-go)\n# DASHSCOPE_CP_API_KEY → qwclaude (Bailian Qwen, Coding Plan)\n# DASHSCOPE_TP_API_KEY → qwclaude (Bailian Qwen, Token Plan)\n# GLM_API_KEY → glmclaude (ZhipuAI GLM)\n# KIMI_API_KEY → kmclaude (Moonshot Kimi)\n# ARK_API_KEY → arkclaude (Volcengine Ark)\n# LONGCAT_API_KEY → lcclaude (Meituan LongCat)\n# MINIMAX_API_KEY → mxclaude (MiniMax)\n# HY_API_KEY → hyclaude (Tencent TokenHub)\n# SF_API_KEY → sfclaude (SiliconFlow)\n#\n# Quick start:\n# chmod +x xclaude && ./xclaude\n#\n# All args are forwarded to the underlying launcher, so everything works:\n# xclaude fast long effort max # fast model, 1M context, max effort\n# xclaude kimi # on TokenHub → kimi-k2.7-code; on Ark → same\n# xclaude --help # forwarded to claude\n#\n# If multiple keys are set, the first found wins (with a notice).\n# Set XCLAUDE_PREFER=dsclaude|... to force a specific provider.\n\nset -euo pipefail\n\n# Resolve symlink to find the real script directory.\n_SELF=\"$0\"\nif [ -L \"$_SELF\" ]; then\n _LINK=\"$(readlink \"$_SELF\")\"\n case \"$_LINK\" in\n /*) _SELF=\"$_LINK\" ;;\n *) _SELF=\"$(cd \"$(dirname \"$_SELF\")\" && pwd)/$_LINK\" ;;\n esac\nfi\nSELF_DIR=\"$(cd \"$(dirname \"$_SELF\")\" && pwd)\"\nif [ -f \"$SELF_DIR/lib/common.sh\" ]; then source \"$SELF_DIR/lib/common.sh\"\nelif [ -f \"$SELF_DIR/../lib/common.sh\" ]; then source \"$SELF_DIR/../lib/common.sh\"\nelse echo \"xclaude: cannot find lib/common.sh. Reinstall or cd to repo.\" >&2; exit 1; fi\n\ncheck_version \"xclaude\" \"$@\"\n\n# ---- Ensure claude is available (called before each exec path) ----------------\n_ensure_claude() {\n if command -v claude >/dev/null 2>&1; then return 0; fi\n echo \"xclaude: 'claude' not found in PATH.\" >&2\n echo \" Install Claude Code: npm install -g @anthropic-ai/claude-code\" >&2\n echo \" Docs: https://docs.anthropic.com/en/docs/claude-code/overview\" >&2\n exit 1\n}\n\n# ---- Resolve the repo directory (for finding launcher scripts) ---------------\nREPO=\"$(find_repo \"XCLAUDE_HOME\")\"\nif [ -z \"$REPO\" ]; then\n echo \"xclaude: cannot find the xxclaude repo.\" >&2\n echo \" Set XCLAUDE_HOME=/path/to/xxclaude or cd into the repo and run ./xclaude\" >&2\n exit 1\nfi\n\n# ---- Extract an API key from env or shell rc files --------------------------\n# Uses the shared extract_key_from_file which skips commented-out lines.\nget_key() {\n local var=\"$1\"\n # 1) Env var.\n if [ -n \"${!var:-}\" ]; then printf '%s' \"${!var}\"; return 0; fi\n # 2) Shell rc files (via shared extract_key_from_file).\n local f candidate\n for f in \"$HOME/.zshrc\" \"$HOME/.bashrc\" \"$HOME/.bash_profile\" \"$HOME/.profile\"; do\n candidate=\"$(extract_key_from_file \"$f\" \"$var\" || true)\"\n if [ -n \"${candidate:-}\" ]; then printf '%s' \"$candidate\"; return 0; fi\n done\n return 1\n}\n\n# ---- Provider registry (key_var → launcher_name, label) ---------------------\n# Order matters: first match wins when multiple keys are set.\nPROVIDERS=(\n \"DEEPSEEK_API_KEY:dsclaude:DeepSeek\"\n \"MIMO_API_KEY:mmclaude:Xiaomi MiMo\"\n \"DASHSCOPE_API_KEY:qwclaude:Bailian Qwen payg\"\n \"DASHSCOPE_CP_API_KEY:qwclaude:Bailian Qwen CodingPlan\"\n \"DASHSCOPE_TP_API_KEY:qwclaude:Bailian Qwen TokenPlan\"\n \"GLM_API_KEY:glmclaude:ZhipuAI GLM\"\n \"KIMI_API_KEY:kmclaude:Moonshot Kimi\"\n \"ARK_API_KEY:arkclaude:Volcengine Ark\"\n \"LONGCAT_API_KEY:lcclaude:Meituan LongCat\"\n \"MINIMAX_API_KEY:mxclaude:MiniMax\"\n \"HY_API_KEY:hyclaude:Tencent TokenHub\"\n \"SF_API_KEY:sfclaude:SiliconFlow\"\n)\n\n# ---- Subcommands: ls, menu -------------------------------------------------\nif [ $# -gt 0 ]; then\n case \"$1\" in\n ls|list)\n printf \"%-20s %-4s %-25s %s\\n\" \"BACKEND\" \"KEY\" \"ENV_VAR\" \"LAUNCHER\"\n printf \"%-20s %-4s %-25s %s\\n\" \"-------\" \"---\" \"-------\" \"--------\"\n for entry in \"${PROVIDERS[@]}\"; do\n IFS=\":\" read -r key_var launcher label <<< \"$entry\"\n status=\"✗\"\n get_key \"$key_var\" >/dev/null 2>&1 && status=\"✓\"\n printf \"%-20s %-4s %-25s %s\\n\" \"$label\" \"$status\" \"$key_var\" \"$launcher\"\n done\n echo \"\"\n echo \"Set any key above and run: xclaude\"\n exit 0\n ;;\n menu|pick)\n echo \"Select a backend (enter number):\"\n echo \"\"\n i=1\n choices=()\n for entry in \"${PROVIDERS[@]}\"; do\n IFS=\":\" read -r key_var launcher label <<< \"$entry\"\n mark=\" \"; extra=\"\"\n if get_key \"$key_var\" >/dev/null 2>&1; then\n mark=\"✓\"; extra=\" ← key set\"\n else\n mark=\"✗\"; extra=\" (key not set)\"\n fi\n printf \" %2d) [%s] %-30s%s\\n\" \"$i\" \"$mark\" \"$label\" \"$extra\"\n choices+=(\"$launcher\")\n i=$((i+1))\n done\n echo \"\"\n read -r -p \"Choice [1-$((i-1))]: \" choice\n idx=\"${choice:-1}\"\n if [ \"$idx\" -ge 1 ] 2>/dev/null && [ \"$idx\" -lt \"$i\" ]; then\n SELECTED=\"${choices[$((idx-1))]}\"\n LAUNCHER_PATH=\"$REPO/$SELECTED\"\n if [ -x \"$LAUNCHER_PATH\" ]; then\n echo \"xclaude: launching $SELECTED...\"\n shift\n _ensure_claude\n exec \"$LAUNCHER_PATH\" \"$@\"\n else\n echo \"xclaude: launcher not found: $LAUNCHER_PATH\" >&2; exit 1\n fi\n else\n echo \"xclaude: invalid choice.\" >&2; exit 1\n fi\n exit 0\n ;;\n help|--help|-h)\n echo \"xclaude — auto-detect API key and launch the right backend.\"\n echo \"\"\n echo \"Usage:\"\n echo \" xclaude [args] Auto-detect and launch\"\n echo \" xclaude ls List all backends and key status\"\n echo \" xclaude menu Interactive backend picker\"\n echo \" xclaude <launcher_args> All args forwarded to launcher\"\n echo \" (fast, long, effort, model aliases...)\"\n echo \"\"\n echo \"Env:\"\n echo \" XCLAUDE_PREFER=<launcher> Force a specific backend\"\n echo \" XCLAUDE_HOME=/path/to/repo Repo location override\"\n exit 0\n ;;\n esac\nfi\n\n# ---- Override via XCLAUDE_PREFER -------------------------------------------\nif [ -n \"${XCLAUDE_PREFER:-}\" ]; then\n FOUND=\"\"\n for entry in \"${PROVIDERS[@]}\"; do\n IFS=\":\" read -r key_var launcher label <<< \"$entry\"\n if [ \"$launcher\" = \"$XCLAUDE_PREFER\" ]; then\n key=\"$(get_key \"$key_var\" || true)\"\n if [ -n \"${key:-}\" ]; then FOUND=\"$launcher:$key:$label\"; break; fi\n fi\n done\n if [ -z \"$FOUND\" ]; then\n echo \"xclaude: XCLAUDE_PREFER=$XCLAUDE_PREFER but that key is not set. Trying auto-detect...\" >&2\n fi\nfi\n\n# ---- Auto-detect -----------------------------------------------------------\nif [ -z \"${FOUND:-}\" ]; then\n FOUND=\"\"\n for entry in \"${PROVIDERS[@]}\"; do\n IFS=\":\" read -r key_var launcher label <<< \"$entry\"\n key=\"$(get_key \"$key_var\" || true)\"\n if [ -n \"${key:-}\" ]; then\n if [ -z \"$FOUND\" ]; then\n FOUND=\"$launcher:$key:$label\"\n else\n # Multiple keys detected — warn but stick with the first.\n echo \"xclaude: multiple API keys detected. Using first found ($label).\" >&2\n echo \" Set XCLAUDE_PREFER=<launcher> to choose a specific provider.\" >&2\n break\n fi\n fi\n done\nfi\n\nif [ -z \"${FOUND:-}\" ]; then\n echo \"❌ xclaude: no known API key found.\" >&2\n echo \" Set one of these in your ~/.zshrc or environment:\" >&2\n echo \" export DEEPSEEK_API_KEY=sk-... # DeepSeek\" >&2\n echo \" export GLM_API_KEY=... # ZhipuAI GLM\" >&2\n echo \" export KIMI_API_KEY=sk-... # Moonshot Kimi\" >&2\n echo \" export DASHSCOPE_API_KEY=sk-... # Bailian Qwen\" >&2\n echo \" export ARK_API_KEY=... # Volcengine Ark\" >&2\n echo \" export LONGCAT_API_KEY=lc-... # Meituan LongCat\" >&2\n echo \" export MINIMAX_API_KEY=... # MiniMax\" >&2\n echo \" export HY_API_KEY=... # Tencent TokenHub\" >&2\n echo \" export SF_API_KEY=sk-... # SiliconFlow\" >&2\n echo \" export MIMO_API_KEY=sk-... # Xiaomi MiMo\" >&2\n echo \" Or use a specific launcher directly: dsclaude, mmclaude, qwclaude, ...\" >&2\n exit 1\nfi\n\nIFS=\":\" read -r LAUNCHER _ VALID_LABEL <<< \"$FOUND\"\nLAUNCHER_PATH=\"$REPO/$LAUNCHER\"\n\nif [ ! -x \"$LAUNCHER_PATH\" ]; then\n echo \"xclaude: launcher not found or not executable at $LAUNCHER_PATH\" >&2\n exit 1\nfi\n\n# Forward ALL remaining args to the underlying launcher.\n# The launcher will handle its own arg parsing (fast, long, effort, model aliases, etc.).\necho \"xclaude: detected $VALID_LABEL → delegating to $LAUNCHER\"\n_ensure_claude\nexec \"$LAUNCHER_PATH\" \"$@\"\n"}}, "docs/zh.md": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785595190.537779, "n": 6736, "h": "a24a31a144fe42c1", "c": "---\ntitle: dsclaude\ndescription: 面向非 Anthropic 后端的启动器工具集\n---\n\n[English](./) · **中文** · [GitHub](https://github.com/Agents365-ai/dsclaude) · [Gitee 镜像](https://gitee.com/Agents365-ai/dsclaude)\n\n让 [Claude Code](https://claude.ai/code) 和 Claude Desktop 接入 DeepSeek、小米 MiMo 等第三方模型后端的小工具集。\n\n**作者:** [Agents365-ai](https://github.com/Agents365-ai) · [Bilibili](https://space.bilibili.com/441831884)\n\n---\n\n## 工具一览\n\n| 工具 | 作用 | 平台 | 后端 |\n|------|------|------|------|\n| **[dsclaude](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude)** | Claude Code CLI 启动器 | macOS / Linux | DeepSeek |\n| **[mmclaude](https://github.com/Agents365-ai/dsclaude/blob/main/mmclaude)** | Claude Code CLI 启动器 | macOS / Linux | 小米 MiMo |\n| **[dsclaude-desktop](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude-desktop)** | Claude Desktop GUI 配置器 | macOS | DeepSeek |\n| **[dsclaude-desktop.ps1](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude-desktop.ps1)** | Claude Desktop GUI 配置器 | Windows | DeepSeek |\n| **[skills/deepseek-vision](https://github.com/Agents365-ai/dsclaude/tree/main/skills/deepseek-vision)** | 视觉识别 skill(零依赖) | macOS / Linux | DashScope Qwen |\n| **[dsvision-mcp](https://github.com/Agents365-ai/dsclaude/blob/main/dsvision-mcp)** | 视觉识别 MCP 服务 | macOS / Linux | DashScope Qwen |\n\n---\n\n## macOS 快速开始\n\n```bash\ngit clone https://github.com/Agents365-ai/dsclaude.git\ncd dsclaude\nchmod +x dsclaude\n./dsclaude\n```\n\n---\n\n## dsclaude — Claude Code 接入 DeepSeek\n\n遵循 [DeepSeek Anthropic API](https://api-docs.deepseek.com/guides/anthropic_api) 指南。\n\n```bash\nexport DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 添加到 ~/.zshrc\n\ndsclaude # 默认 deepseek-v4-pro(完整推理)\ndsclaude fast # deepseek-v4-flash(更快更便宜)\ndsclaude long # 1M 上下文窗口\ndsclaude long fast # 1M + flash\n```\n\n自动设置 DeepSeek 推荐的环境变量(`ANTHROPIC_BASE_URL`、模型映射、`CLAUDE_CODE_EFFORT_LEVEL=max`),并在 `/model` 选择器中暴露备选模型。上下文窗口上限可通过 `DSCLAUDE_MAX_TOKENS` 覆盖,effort 级别通过 `DSCLAUDE_EFFORT` 覆盖。\n\n> 两个模型都原生支持 1M token,在 Claude Code 中需加 `[1m]` 后缀(如 `deepseek-v4-pro[1m]`),脚本已自动处理。\n\n---\n\n## mmclaude — Claude Code 接入小米 MiMo\n\n```bash\nexport MIMO_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 按量付费\n# 或\nexport MIMO_API_KEY=tp-xxxxxxxxxxxxxxxxxx # Token Plan\n\nmmclaude # 启动 mimo-v2.5-pro\nmmclaude update # git pull 拉取更新\n```\n\n按 key 前缀自动选择 base URL(`sk-*` → 公网,`tp-*` → Token Plan),可用 `MIMO_BASE_URL` 覆盖。所有模型槽位都指向 `mimo-v2.5-pro`,并自动 unset `ANTHROPIC_API_KEY`(避免遮蔽 bearer token)。\n\n---\n\n## dsclaude-desktop — Claude Desktop GUI 配置器\n\n一键配置 Claude Desktop **内置**的 Third-Party Inference 功能(Developer 菜单),预填 DeepSeek 参数并重启 App。\n\n### 前置条件\n\n1. 已安装 Claude Desktop([claude.ai/download](https://claude.ai/download))\n2. 已启用 Developer Mode(Help → Troubleshooting → Enable Developer Mode,一次即可)\n3. 已设置 `DEEPSEEK_API_KEY` 环境变量\n\n### 用法(macOS)\n\n```bash\nexport DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./dsclaude-desktop # 配置并重启\n./dsclaude-desktop -h # 帮助\n```\n\n脚本在 `~/Library/Application Support/Claude-3p/configLibrary/` 下生成配置 entry,将其设为 `appliedId`,然后重启 App。原本通过 GUI 添加的其他 entry 不受影响。\n\n### 模式切换\n\nClaude Desktop 启动选择器原生支持 Anthropic ↔ Gateway 切换,无需 `--revert`。在 App 内点头像 → Disconnect,下次启动时选另一个入口即可。\n\n> 唯一不可用的功能是经典 **Chat**(依赖 Anthropic 托管服务且不在 inference API 表面)。需要用 Chat 时切回 Anthropic 模式即可。\n\n### 用法(Windows)\n\n```powershell\n$env:DEEPSEEK_API_KEY = \"sk-xxxxxxxxxxxxxxxxxx\"\npwsh ./dsclaude-desktop.ps1\n```\n\n**无需手动启用 Developer Mode** —— 脚本会自动创建 `developer_settings.json`。\n\n配置目录:`%LOCALAPPDATA%\\Claude-3p\\configLibrary\\`(若为 Store/MSIX 安装,脚本还会额外写入沙箱路径 `LocalCache\\Roaming\\Claude-3p\\configLibrary\\` 作为后备)。\n\n已在 Windows 11 + Claude Desktop 1.7196(Windows Store, arm64)上实测通过。\n\n---\n\n## deepseek-vision skill — 视觉识别(零依赖方案)\n\n给纯文本模型(如 DeepSeek)补上\"看图\"能力的 skill。代理遇到图片时调 `analyze-image` 脚本,发给 Qwen3.6-Flash 识别后将描述返回主模型。\n\n```bash\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./skills/deepseek-vision/analyze-image /path/to/screenshot.png \"图里报的什么错?\"\n./skills/deepseek-vision/analyze-image https://example.com/diagram.png\n```\n\n任何加载 `SKILL.md` 的 agent(Claude Code、Cowork 等)都能用它。默认模型 `qwen3.6-flash`,可通过 `DSVISION_MODEL` 和 `DSVISION_BASE_URL` 切换。\n\n> **限制**:需文件路径或 URL,不支持拖拽/粘贴/「+ → Add files or photos」上传的图片。这类场景请用下方的 **dsvision-mcp**。\n\n---\n\n## dsvision-mcp — 视觉识别(MCP 方案)\n\n功能同上,但以 MCP 服务形式运行,绕过 Cowork 沙箱的两个限制:\n\n1. **网络出口管制** — skill 调 DashScope API 会被沙箱防火墙拦截,MCP 服务跑在沙箱外\n2. **内联图片** — 自动读取 `~/.claude/image-cache/` 中最新缓存,拖拽/粘贴/菜单上传均可正常工作(仅 macOS,Windows Cowork 不缓存内联图)\n\n### 安装\n\n```bash\npip3 install fastmcp requests\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 建议加到 ~/.zshrc\ncd /path/to/dsclaude && pwd # 记下绝对路径\n```\n\n然后根据当前模式,在对应的配置文件中添加 MCP 服务:\n\n| 模式 | 配置文件 |\n|------|----------|\n| 3P/Gateway(通过 `dsclaude-desktop` 使用 DeepSeek) | `~/Library/Application Support/Claude-3p/claude_desktop_config.json` |\n| 标准 Anthropic 模式 | `~/Library/Application Support/Claude/claude_desktop_config.json` |\n\n```json\n{\n \"mcpServers\": {\n \"dsvision\": {\n \"command\": \"/绝对/路径/dsclaude/dsvision-mcp\"\n }\n }\n}\n```\n\n重启 Claude Desktop 后,`analyze_image` 工具自动出现。\n\n### 用法\n\n```\nanalyze_image() # 自动检测最新缓存图片\nanalyze_image(image_path=\"/绝对/路径/foo.png\")\nanalyze_image(focus=\"图里报的什么错?\") # 自定义 prompt\n```\n\n### 常见问题\n\n| 现象 | 排查方向 |\n|------|----------|\n| 工具不显示 | 配置文件路径选错 / JSON 格式错误(用 `python3 -m json.tool` 校验) |\n| 工具报错 | `DASHSCOPE_API_KEY` 未设置 |\n| `ModuleNotFoundError` | 用 `pip3` 而非 `pip` |\n| 找不到图片 | 传绝对路径,或检查 `~/.claude/image-cache/` 是否存在 |\n\n### skill vs MCP 怎么选\n\n| 场景 | 推荐 |\n|------|------|\n| Claude Code (CLI),给明确路径 | `skills/deepseek-vision`(零依赖) |\n| Cowork / Desktop,拖拽/粘贴内联图 | `dsvision-mcp`(唯一能用的) |\n| Cowork,给明确路径,不介意沙箱限制 | 两者均可 |\n\n---\n\n## 社区\n\n- **Discord:** <https://discord.gg/79JF5Atuk>\n- **微信:** 扫描下方二维码\n\n<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/agents365ai_wechat_1.png\" width=\"200\" alt=\"微信交流群\">\n</p>\n\n## 赞赏支持\n\n如果这些脚本为你节省了时间,欢迎支持作者:\n\n<table>\n <tr>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/wechat-pay.png\" width=\"150\" alt=\"微信支付\"><br><b>微信支付</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/alipay.png\" width=\"150\" alt=\"支付宝\"><br><b>支付宝</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/buymeacoffee.png\" width=\"150\" alt=\"Buy Me a Coffee\"><br><b>Buy Me a Coffee</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/awarding/award.gif\" width=\"150\" alt=\"打赏\"><br><b>打赏鼓励</b></td>\n </tr>\n</table>\n\n## 开源协议\n\n[CC BY-NC 4.0](https://github.com/Agents365-ai/dsclaude/blob/main/LICENSE.md) — 非商业用途免费。**商业使用需获得授权。**\n"}, "19aaa2af30c47c7e1a85baed155ff3f239f61d59": {"t": 1785758055.877773, "n": 6736, "h": "a24a31a144fe42c1", "c": "---\ntitle: dsclaude\ndescription: 面向非 Anthropic 后端的启动器工具集\n---\n\n[English](./) · **中文** · [GitHub](https://github.com/Agents365-ai/dsclaude) · [Gitee 镜像](https://gitee.com/Agents365-ai/dsclaude)\n\n让 [Claude Code](https://claude.ai/code) 和 Claude Desktop 接入 DeepSeek、小米 MiMo 等第三方模型后端的小工具集。\n\n**作者:** [Agents365-ai](https://github.com/Agents365-ai) · [Bilibili](https://space.bilibili.com/441831884)\n\n---\n\n## 工具一览\n\n| 工具 | 作用 | 平台 | 后端 |\n|------|------|------|------|\n| **[dsclaude](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude)** | Claude Code CLI 启动器 | macOS / Linux | DeepSeek |\n| **[mmclaude](https://github.com/Agents365-ai/dsclaude/blob/main/mmclaude)** | Claude Code CLI 启动器 | macOS / Linux | 小米 MiMo |\n| **[dsclaude-desktop](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude-desktop)** | Claude Desktop GUI 配置器 | macOS | DeepSeek |\n| **[dsclaude-desktop.ps1](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude-desktop.ps1)** | Claude Desktop GUI 配置器 | Windows | DeepSeek |\n| **[skills/deepseek-vision](https://github.com/Agents365-ai/dsclaude/tree/main/skills/deepseek-vision)** | 视觉识别 skill(零依赖) | macOS / Linux | DashScope Qwen |\n| **[dsvision-mcp](https://github.com/Agents365-ai/dsclaude/blob/main/dsvision-mcp)** | 视觉识别 MCP 服务 | macOS / Linux | DashScope Qwen |\n\n---\n\n## macOS 快速开始\n\n```bash\ngit clone https://github.com/Agents365-ai/dsclaude.git\ncd dsclaude\nchmod +x dsclaude\n./dsclaude\n```\n\n---\n\n## dsclaude — Claude Code 接入 DeepSeek\n\n遵循 [DeepSeek Anthropic API](https://api-docs.deepseek.com/guides/anthropic_api) 指南。\n\n```bash\nexport DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 添加到 ~/.zshrc\n\ndsclaude # 默认 deepseek-v4-pro(完整推理)\ndsclaude fast # deepseek-v4-flash(更快更便宜)\ndsclaude long # 1M 上下文窗口\ndsclaude long fast # 1M + flash\n```\n\n自动设置 DeepSeek 推荐的环境变量(`ANTHROPIC_BASE_URL`、模型映射、`CLAUDE_CODE_EFFORT_LEVEL=max`),并在 `/model` 选择器中暴露备选模型。上下文窗口上限可通过 `DSCLAUDE_MAX_TOKENS` 覆盖,effort 级别通过 `DSCLAUDE_EFFORT` 覆盖。\n\n> 两个模型都原生支持 1M token,在 Claude Code 中需加 `[1m]` 后缀(如 `deepseek-v4-pro[1m]`),脚本已自动处理。\n\n---\n\n## mmclaude — Claude Code 接入小米 MiMo\n\n```bash\nexport MIMO_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 按量付费\n# 或\nexport MIMO_API_KEY=tp-xxxxxxxxxxxxxxxxxx # Token Plan\n\nmmclaude # 启动 mimo-v2.5-pro\nmmclaude update # git pull 拉取更新\n```\n\n按 key 前缀自动选择 base URL(`sk-*` → 公网,`tp-*` → Token Plan),可用 `MIMO_BASE_URL` 覆盖。所有模型槽位都指向 `mimo-v2.5-pro`,并自动 unset `ANTHROPIC_API_KEY`(避免遮蔽 bearer token)。\n\n---\n\n## dsclaude-desktop — Claude Desktop GUI 配置器\n\n一键配置 Claude Desktop **内置**的 Third-Party Inference 功能(Developer 菜单),预填 DeepSeek 参数并重启 App。\n\n### 前置条件\n\n1. 已安装 Claude Desktop([claude.ai/download](https://claude.ai/download))\n2. 已启用 Developer Mode(Help → Troubleshooting → Enable Developer Mode,一次即可)\n3. 已设置 `DEEPSEEK_API_KEY` 环境变量\n\n### 用法(macOS)\n\n```bash\nexport DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./dsclaude-desktop # 配置并重启\n./dsclaude-desktop -h # 帮助\n```\n\n脚本在 `~/Library/Application Support/Claude-3p/configLibrary/` 下生成配置 entry,将其设为 `appliedId`,然后重启 App。原本通过 GUI 添加的其他 entry 不受影响。\n\n### 模式切换\n\nClaude Desktop 启动选择器原生支持 Anthropic ↔ Gateway 切换,无需 `--revert`。在 App 内点头像 → Disconnect,下次启动时选另一个入口即可。\n\n> 唯一不可用的功能是经典 **Chat**(依赖 Anthropic 托管服务且不在 inference API 表面)。需要用 Chat 时切回 Anthropic 模式即可。\n\n### 用法(Windows)\n\n```powershell\n$env:DEEPSEEK_API_KEY = \"sk-xxxxxxxxxxxxxxxxxx\"\npwsh ./dsclaude-desktop.ps1\n```\n\n**无需手动启用 Developer Mode** —— 脚本会自动创建 `developer_settings.json`。\n\n配置目录:`%LOCALAPPDATA%\\Claude-3p\\configLibrary\\`(若为 Store/MSIX 安装,脚本还会额外写入沙箱路径 `LocalCache\\Roaming\\Claude-3p\\configLibrary\\` 作为后备)。\n\n已在 Windows 11 + Claude Desktop 1.7196(Windows Store, arm64)上实测通过。\n\n---\n\n## deepseek-vision skill — 视觉识别(零依赖方案)\n\n给纯文本模型(如 DeepSeek)补上\"看图\"能力的 skill。代理遇到图片时调 `analyze-image` 脚本,发给 Qwen3.6-Flash 识别后将描述返回主模型。\n\n```bash\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./skills/deepseek-vision/analyze-image /path/to/screenshot.png \"图里报的什么错?\"\n./skills/deepseek-vision/analyze-image https://example.com/diagram.png\n```\n\n任何加载 `SKILL.md` 的 agent(Claude Code、Cowork 等)都能用它。默认模型 `qwen3.6-flash`,可通过 `DSVISION_MODEL` 和 `DSVISION_BASE_URL` 切换。\n\n> **限制**:需文件路径或 URL,不支持拖拽/粘贴/「+ → Add files or photos」上传的图片。这类场景请用下方的 **dsvision-mcp**。\n\n---\n\n## dsvision-mcp — 视觉识别(MCP 方案)\n\n功能同上,但以 MCP 服务形式运行,绕过 Cowork 沙箱的两个限制:\n\n1. **网络出口管制** — skill 调 DashScope API 会被沙箱防火墙拦截,MCP 服务跑在沙箱外\n2. **内联图片** — 自动读取 `~/.claude/image-cache/` 中最新缓存,拖拽/粘贴/菜单上传均可正常工作(仅 macOS,Windows Cowork 不缓存内联图)\n\n### 安装\n\n```bash\npip3 install fastmcp requests\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 建议加到 ~/.zshrc\ncd /path/to/dsclaude && pwd # 记下绝对路径\n```\n\n然后根据当前模式,在对应的配置文件中添加 MCP 服务:\n\n| 模式 | 配置文件 |\n|------|----------|\n| 3P/Gateway(通过 `dsclaude-desktop` 使用 DeepSeek) | `~/Library/Application Support/Claude-3p/claude_desktop_config.json` |\n| 标准 Anthropic 模式 | `~/Library/Application Support/Claude/claude_desktop_config.json` |\n\n```json\n{\n \"mcpServers\": {\n \"dsvision\": {\n \"command\": \"/绝对/路径/dsclaude/dsvision-mcp\"\n }\n }\n}\n```\n\n重启 Claude Desktop 后,`analyze_image` 工具自动出现。\n\n### 用法\n\n```\nanalyze_image() # 自动检测最新缓存图片\nanalyze_image(image_path=\"/绝对/路径/foo.png\")\nanalyze_image(focus=\"图里报的什么错?\") # 自定义 prompt\n```\n\n### 常见问题\n\n| 现象 | 排查方向 |\n|------|----------|\n| 工具不显示 | 配置文件路径选错 / JSON 格式错误(用 `python3 -m json.tool` 校验) |\n| 工具报错 | `DASHSCOPE_API_KEY` 未设置 |\n| `ModuleNotFoundError` | 用 `pip3` 而非 `pip` |\n| 找不到图片 | 传绝对路径,或检查 `~/.claude/image-cache/` 是否存在 |\n\n### skill vs MCP 怎么选\n\n| 场景 | 推荐 |\n|------|------|\n| Claude Code (CLI),给明确路径 | `skills/deepseek-vision`(零依赖) |\n| Cowork / Desktop,拖拽/粘贴内联图 | `dsvision-mcp`(唯一能用的) |\n| Cowork,给明确路径,不介意沙箱限制 | 两者均可 |\n\n---\n\n## 社区\n\n- **Discord:** <https://discord.gg/79JF5Atuk>\n- **微信:** 扫描下方二维码\n\n<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/agents365ai_wechat_1.png\" width=\"200\" alt=\"微信交流群\">\n</p>\n\n## 赞赏支持\n\n如果这些脚本为你节省了时间,欢迎支持作者:\n\n<table>\n <tr>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/wechat-pay.png\" width=\"150\" alt=\"微信支付\"><br><b>微信支付</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/alipay.png\" width=\"150\" alt=\"支付宝\"><br><b>支付宝</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/buymeacoffee.png\" width=\"150\" alt=\"Buy Me a Coffee\"><br><b>Buy Me a Coffee</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/awarding/award.gif\" width=\"150\" alt=\"打赏\"><br><b>打赏鼓励</b></td>\n </tr>\n</table>\n\n## 开源协议\n\n[CC BY-NC 4.0](https://github.com/Agents365-ai/dsclaude/blob/main/LICENSE.md) — 非商业用途免费。**商业使用需获得授权。**\n"}, "017b91e3d433498894a800f92646ce146a34a892": {"t": 1785758057.5355337, "n": 6758, "h": "91a290ce52ce422a", "c": "---\ntitle: dsclaude\ndescription: 面向非 Anthropic 后端的启动器工具集\n---\n\n[English](./) · **中文** · [GitHub](https://github.com/Agents365-ai/dsclaude) · [Gitee 镜像](https://gitee.com/Agents365-ai/dsclaude)\n\n让 [Claude Code](https://claude.ai/code) 和 Claude Desktop 接入 DeepSeek、小米 MiMo 等第三方模型后端的小工具集。\n\n**作者:** [Agents365-ai](https://github.com/Agents365-ai) · [Bilibili](https://space.bilibili.com/441831884)\n\n---\n\n## 工具一览\n\n| 工具 | 作用 | 平台 | 后端 |\n|------|------|------|------|\n| **[dsclaude](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude)** | Claude Code CLI 启动器 | macOS / Linux | DeepSeek |\n| **[mmclaude](https://github.com/Agents365-ai/dsclaude/blob/main/mmclaude)** | Claude Code CLI 启动器 | macOS / Linux | 小米 MiMo |\n| **[dsclaude-desktop](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude-desktop)** | Claude Desktop GUI 配置器 | macOS | DeepSeek |\n| **[dsclaude-desktop.ps1](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude-desktop.ps1)** | Claude Desktop GUI 配置器 | Windows | DeepSeek |\n| **[skills/deepseek-vision](https://github.com/Agents365-ai/dsclaude/tree/main/skills/deepseek-vision)** | 视觉识别 skill(零依赖) | macOS / Linux | DashScope Qwen |\n| **[dsvision-mcp](https://github.com/Agents365-ai/dsclaude/blob/main/dsvision-mcp)** | 视觉识别 MCP 服务 | macOS / Linux | DashScope Qwen |\n\n---\n\n## macOS 快速开始\n\n```bash\ngit clone https://github.com/Agents365-ai/dsclaude.git\ncd dsclaude\nchmod +x dsclaude\n./dsclaude\n```\n\n---\n\n## dsclaude — Claude Code 接入 DeepSeek\n\n遵循 [DeepSeek Anthropic API](https://api-docs.deepseek.com/guides/anthropic_api) 指南。\n\n```bash\nexport DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 添加到 ~/.zshrc\n\ndsclaude # 默认 deepseek-v4-pro(完整推理)\ndsclaude fast # deepseek-v4-flash(更快更便宜)\ndsclaude long # 1M 上下文窗口\ndsclaude long fast # 1M + flash\n```\n\n自动设置 DeepSeek 推荐的环境变量(`ANTHROPIC_BASE_URL`、模型映射、`CLAUDE_CODE_EFFORT_LEVEL=max`),并在 `/model` 选择器中暴露备选模型。上下文窗口上限可通过 `DSCLAUDE_MAX_TOKENS` 覆盖,effort 级别通过 `DSCLAUDE_EFFORT` 覆盖。\n\n> 两个模型都原生支持 1M token,在 Claude Code 中需加 `[1m]` 后缀(如 `deepseek-v4-pro[1m]`),脚本已自动处理。\n\n---\n\n## mmclaude — Claude Code 接入小米 MiMo\n\n```bash\nexport MIMO_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 按量付费\n# 或\nexport MIMO_API_KEY=tp-xxxxxxxxxxxxxxxxxx # Token Plan\n\nmmclaude # 启动 mimo-v2.5-pro\nmmclaude update # git pull 拉取更新\n```\n\n按 key 前缀自动选择 base URL(`sk-*` → 公网,`tp-*` → Token Plan),可用 `MIMO_BASE_URL` 覆盖。所有模型槽位都指向 `mimo-v2.5-pro`,并自动 unset `ANTHROPIC_API_KEY`(避免遮蔽 bearer token)。\n\n---\n\n## dsclaude-desktop — Claude Desktop GUI 配置器\n\n一键配置 Claude Desktop **内置**的 Third-Party Inference 功能(Developer 菜单),预填 DeepSeek 参数并重启 App。\n\n### 前置条件\n\n1. 已安装 Claude Desktop([claude.ai/download](https://claude.ai/download))\n2. 已启用 Developer Mode(Help → Troubleshooting → Enable Developer Mode,一次即可)\n3. 已设置 `DEEPSEEK_API_KEY` 环境变量\n\n### 用法(macOS)\n\n```bash\nexport DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./dsclaude-desktop # 配置并重启\n./dsclaude-desktop -h # 帮助\n```\n\n脚本在 `~/Library/Application Support/Claude-3p/configLibrary/` 下生成配置 entry,将其设为 `appliedId`,然后重启 App。原本通过 GUI 添加的其他 entry 不受影响。\n\n### 模式切换\n\nClaude Desktop 启动选择器原生支持 Anthropic ↔ Gateway 切换,无需 `--revert`。在 App 内点头像 → Disconnect,下次启动时选另一个入口即可。\n\n> 唯一不可用的功能是经典 **Chat**(依赖 Anthropic 托管服务且不在 inference API 表面)。需要用 Chat 时切回 Anthropic 模式即可。\n\n### 用法(Windows)\n\n```powershell\n$env:DEEPSEEK_API_KEY = \"sk-xxxxxxxxxxxxxxxxxx\"\npwsh ./dsclaude-desktop.ps1\n```\n\n**无需手动启用 Developer Mode** —— 脚本会自动创建 `developer_settings.json`。\n\n配置目录:`%LOCALAPPDATA%\\Claude-3p\\configLibrary\\`(若为 Store/MSIX 安装,脚本还会额外写入沙箱路径 `LocalCache\\Roaming\\Claude-3p\\configLibrary\\` 作为后备)。\n\n已在 Windows 11 + Claude Desktop 1.7196(Windows Store, arm64)上实测通过。\n\n---\n\n## deepseek-vision skill — 视觉识别(零依赖方案)\n\n给纯文本模型(如 DeepSeek)补上\"看图\"能力的 skill。代理遇到图片时调 `analyze-image` 脚本,发给 Qwen3.6-Flash 识别后将描述返回主模型。\n\n```bash\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./skills/deepseek-vision/analyze-image /path/to/screenshot.png \"图里报的什么错?\"\n./skills/deepseek-vision/analyze-image https://example.com/diagram.png\n```\n\n任何加载 `SKILL.md` 的 agent(Claude Code、Cowork 等)都能用它。默认模型 `qwen3.6-flash`,可通过 `DSVISION_MODEL` 和 `DSVISION_BASE_URL` 切换。\n\n> **限制**:需文件路径或 URL,不支持拖拽/粘贴/「+ → Add files or photos」上传的图片。这类场景请用下方的 **dsvision-mcp**。\n\n---\n\n## dsvision-mcp — 视觉识别(MCP 方案)\n\n功能同上,但以 MCP 服务形式运行,绕过 Cowork 沙箱的两个限制:\n\n1. **网络出口管制** — skill 调 DashScope API 会被沙箱防火墙拦截,MCP 服务跑在沙箱外\n2. **内联图片** — 自动读取 `~/.claude/image-cache/` 中最新缓存,拖拽/粘贴/菜单上传均可正常工作(仅 macOS,Windows Cowork 不缓存内联图)\n\n### 安装\n\n```bash\npip3 install fastmcp requests\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 建议加到 ~/.zshrc\ncd /path/to/dsclaude && pwd # 记下绝对路径\n```\n\n然后根据当前模式,在对应的配置文件中添加 MCP 服务:\n\n| 模式 | 配置文件 |\n|------|----------|\n| 3P/Gateway(通过 `dsclaude-desktop` 使用 DeepSeek) | `~/Library/Application Support/Claude-3p/claude_desktop_config.json` |\n| 标准 Anthropic 模式 | `~/Library/Application Support/Claude/claude_desktop_config.json` |\n\n```json\n{\n \"mcpServers\": {\n \"dsvision\": {\n \"command\": \"/绝对/路径/dsclaude/dsvision-mcp\"\n }\n }\n}\n```\n\n重启 Claude Desktop 后,`analyze_image` 工具自动出现。\n\n### 用法\n\n```\nanalyze_image() # 自动检测最新缓存图片\nanalyze_image(image_path=\"/绝对/路径/foo.png\")\nanalyze_image(focus=\"图里报的什么错?\") # 自定义 prompt\n```\n\n### 常见问题\n\n| 现象 | 排查方向 |\n|------|----------|\n| 工具不显示 | 配置文件路径选错 / JSON 格式错误(用 `python3 -m json.tool` 校验) |\n| 工具报错 | `DASHSCOPE_API_KEY` 未设置 |\n| `ModuleNotFoundError` | 用 `pip3` 而非 `pip` |\n| 找不到图片 | 传绝对路径,或检查 `~/.claude/image-cache/` 是否存在 |\n\n### skill vs MCP 怎么选\n\n| 场景 | 推荐 |\n|------|------|\n| Claude Code (CLI),给明确路径 | `skills/deepseek-vision`(零依赖) |\n| Cowork / Desktop,拖拽/粘贴内联图 | `dsvision-mcp`(唯一能用的) |\n| Cowork,给明确路径,不介意沙箱限制 | 两者均可 |\n\n---\n\n## 社区\n\n- **Discord:** <https://discord.gg/79JF5Atuk>\n- **微信:** 扫描下方二维码\n\n<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/agents365ai_wechat_1.png\" width=\"200\" alt=\"微信交流群\">\n</p>\n\n## 赞赏支持\n\n如果这些脚本为你节省了时间,欢迎支持作者:\n\n<table>\n <tr>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/wechat-pay.png\" width=\"150\" alt=\"微信支付\"><br><b>微信支付</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/alipay.png\" width=\"150\" alt=\"支付宝\"><br><b>支付宝</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/buymeacoffee.png\" width=\"150\" alt=\"Buy Me a Coffee\"><br><b>Buy Me a Coffee</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/awarding/award.gif\" width=\"150\" alt=\"打赏\"><br><b>打赏鼓励</b></td>\n </tr>\n</table>\n\n## 开源协议\n\n[PolyForm Noncommercial 1.0.0](https://github.com/Agents365-ai/dsclaude/blob/main/LICENSE.md) — 个人、科研、教育等非商业用途免费。**禁止商业使用。**\n"}, "6cd1a6909bee21e91a0c849547299a89e547c57c": {"t": 1785758060.4822056, "n": 6637, "h": "bdf6828ac1e1dbcb", "c": "---\ntitle: dsclaude\ndescription: 面向非 Anthropic 后端的启动器工具集\n---\n\n[English](./) · **中文** · [GitHub](https://github.com/Agents365-ai/dsclaude) · [Gitee 镜像](https://gitee.com/Agents365-ai/dsclaude)\n\n让 [Claude Code](https://claude.ai/code) 和 Claude Desktop 接入 DeepSeek、小米 MiMo 等第三方模型后端的小工具集。\n\n**作者:** [Agents365-ai](https://github.com/Agents365-ai) · [Bilibili](https://space.bilibili.com/441831884)\n\n---\n\n## 工具一览\n\n| 工具 | 作用 | 平台 | 后端 |\n|------|------|------|------|\n| **[dsclaude](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude)** | Claude Code CLI 启动器 | macOS / Linux | DeepSeek |\n| **[mmclaude](https://github.com/Agents365-ai/dsclaude/blob/main/mmclaude)** | Claude Code CLI 启动器 | macOS / Linux | 小米 MiMo |\n| **[dsclaude-desktop](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude-desktop)** | Claude Desktop GUI 配置器 | macOS | DeepSeek |\n| **[dsclaude-desktop.ps1](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude-desktop.ps1)** | Claude Desktop GUI 配置器 | Windows | DeepSeek |\n| **[skills/deepseek-vision](https://github.com/Agents365-ai/dsclaude/tree/main/skills/deepseek-vision)** | 视觉识别 skill(零依赖) | macOS / Linux | DashScope Qwen |\n| **[dsvision-mcp](https://github.com/Agents365-ai/dsclaude/blob/main/dsvision-mcp)** | 视觉识别 MCP 服务 | macOS / Linux | DashScope Qwen |\n\n---\n\n## macOS 快速开始\n\n```bash\ngit clone https://github.com/Agents365-ai/dsclaude.git\ncd dsclaude\nchmod +x dsclaude\n./dsclaude\n```\n\n---\n\n## dsclaude — Claude Code 接入 DeepSeek\n\n遵循 [DeepSeek Anthropic API](https://api-docs.deepseek.com/guides/anthropic_api) 指南。\n\n```bash\nexport DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 添加到 ~/.zshrc\n\ndsclaude # 默认 deepseek-v4-pro(完整推理)\ndsclaude fast # deepseek-v4-flash(更快更便宜)\ndsclaude long # 1M 上下文窗口\ndsclaude long fast # 1M + flash\n```\n\n自动设置 DeepSeek 推荐的环境变量(`ANTHROPIC_BASE_URL`、模型映射、`CLAUDE_CODE_EFFORT_LEVEL=max`),并在 `/model` 选择器中暴露备选模型。上下文窗口上限可通过 `DSCLAUDE_MAX_TOKENS` 覆盖,effort 级别通过 `DSCLAUDE_EFFORT` 覆盖。\n\n> 两个模型都原生支持 1M token,在 Claude Code 中需加 `[1m]` 后缀(如 `deepseek-v4-pro[1m]`),脚本已自动处理。\n\n---\n\n## mmclaude — Claude Code 接入小米 MiMo\n\n```bash\nexport MIMO_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 按量付费\n# 或\nexport MIMO_API_KEY=tp-xxxxxxxxxxxxxxxxxx # Token Plan\n\nmmclaude # 启动 mimo-v2.5-pro\nmmclaude update # git pull 拉取更新\n```\n\n按 key 前缀自动选择 base URL(`sk-*` → 公网,`tp-*` → Token Plan),可用 `MIMO_BASE_URL` 覆盖。所有模型槽位都指向 `mimo-v2.5-pro`,并自动 unset `ANTHROPIC_API_KEY`(避免遮蔽 bearer token)。\n\n---\n\n## dsclaude-desktop — Claude Desktop GUI 配置器\n\n一键配置 Claude Desktop **内置**的 Third-Party Inference 功能(Developer 菜单),预填 DeepSeek 参数并重启 App。\n\n### 前置条件\n\n1. 已安装 Claude Desktop([claude.ai/download](https://claude.ai/download))\n2. 已启用 Developer Mode(Help → Troubleshooting → Enable Developer Mode,一次即可)\n3. 已设置 `DEEPSEEK_API_KEY` 环境变量\n\n### 用法(macOS)\n\n```bash\nexport DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./dsclaude-desktop # 配置并重启\n./dsclaude-desktop -h # 帮助\n```\n\n脚本在 `~/Library/Application Support/Claude-3p/configLibrary/` 下生成配置 entry,将其设为 `appliedId`,然后重启 App。原本通过 GUI 添加的其他 entry 不受影响。\n\n### 模式切换\n\nClaude Desktop 启动选择器原生支持 Anthropic ↔ Gateway 切换,无需 `--revert`。在 App 内点头像 → Disconnect,下次启动时选另一个入口即可。\n\n> 唯一不可用的功能是经典 **Chat**(依赖 Anthropic 托管服务且不在 inference API 表面)。需要用 Chat 时切回 Anthropic 模式即可。\n\n### 用法(Windows)\n\n```powershell\n$env:DEEPSEEK_API_KEY = \"sk-xxxxxxxxxxxxxxxxxx\"\npwsh ./dsclaude-desktop.ps1\n```\n\n**无需手动启用 Developer Mode** —— 脚本会自动创建 `developer_settings.json`。\n\n配置目录:`%LOCALAPPDATA%\\Claude-3p\\configLibrary\\`(若为 Store/MSIX 安装,脚本还会额外写入沙箱路径 `LocalCache\\Roaming\\Claude-3p\\configLibrary\\` 作为后备)。\n\n已在 Windows 11 + Claude Desktop 1.7196(Windows Store, arm64)上实测通过。\n\n---\n\n## deepseek-vision skill — 视觉识别(零依赖方案)\n\n给纯文本模型(如 DeepSeek)补上\"看图\"能力的 skill。代理遇到图片时调 `analyze-image` 脚本,发给 Qwen3.6-Flash 识别后将描述返回主模型。\n\n```bash\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./skills/deepseek-vision/analyze-image /path/to/screenshot.png \"图里报的什么错?\"\n./skills/deepseek-vision/analyze-image https://example.com/diagram.png\n```\n\n任何加载 `SKILL.md` 的 agent(Claude Code、Cowork 等)都能用它。默认模型 `qwen3.6-flash`,可通过 `DSVISION_MODEL` 和 `DSVISION_BASE_URL` 切换。\n\n> **限制**:需文件路径或 URL,不支持拖拽/粘贴/「+ → Add files or photos」上传的图片。这类场景请用下方的 **dsvision-mcp**。\n\n---\n\n## dsvision-mcp — 视觉识别(MCP 方案)\n\n功能同上,但以 MCP 服务形式运行,绕过 Cowork 沙箱的两个限制:\n\n1. **网络出口管制** — skill 调 DashScope API 会被沙箱防火墙拦截,MCP 服务跑在沙箱外\n2. **内联图片** — 自动读取 `~/.claude/image-cache/` 中最新缓存,拖拽/粘贴/菜单上传均可正常工作(仅 macOS,Windows Cowork 不缓存内联图)\n\n### 安装\n\n```bash\npip3 install fastmcp requests\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 建议加到 ~/.zshrc\ncd /path/to/dsclaude && pwd # 记下绝对路径\n```\n\n然后根据当前模式,在对应的配置文件中添加 MCP 服务:\n\n| 模式 | 配置文件 |\n|------|----------|\n| 3P/Gateway(通过 `dsclaude-desktop` 使用 DeepSeek) | `~/Library/Application Support/Claude-3p/claude_desktop_config.json` |\n| 标准 Anthropic 模式 | `~/Library/Application Support/Claude/claude_desktop_config.json` |\n\n```json\n{\n \"mcpServers\": {\n \"dsvision\": {\n \"command\": \"/绝对/路径/dsclaude/dsvision-mcp\"\n }\n }\n}\n```\n\n重启 Claude Desktop 后,`analyze_image` 工具自动出现。\n\n### 用法\n\n```\nanalyze_image() # 自动检测最新缓存图片\nanalyze_image(image_path=\"/绝对/路径/foo.png\")\nanalyze_image(focus=\"图里报的什么错?\") # 自定义 prompt\n```\n\n### 常见问题\n\n| 现象 | 排查方向 |\n|------|----------|\n| 工具不显示 | 配置文件路径选错 / JSON 格式错误(用 `python3 -m json.tool` 校验) |\n| 工具报错 | `DASHSCOPE_API_KEY` 未设置 |\n| `ModuleNotFoundError` | 用 `pip3` 而非 `pip` |\n| 找不到图片 | 传绝对路径,或检查 `~/.claude/image-cache/` 是否存在 |\n\n### skill vs MCP 怎么选\n\n| 场景 | 推荐 |\n|------|------|\n| Claude Code (CLI),给明确路径 | `skills/deepseek-vision`(零依赖) |\n| Cowork / Desktop,拖拽/粘贴内联图 | `dsvision-mcp`(唯一能用的) |\n| Cowork,给明确路径,不介意沙箱限制 | 两者均可 |\n\n---\n\n## 社区\n\n- **Discord:** <https://discord.gg/79JF5Atuk>\n- **微信:** 扫描下方二维码\n\n<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/agents365ai_wechat_1.png\" width=\"200\" alt=\"微信交流群\">\n</p>\n\n## 赞赏支持\n\n如果这些脚本为你节省了时间,欢迎支持作者:\n\n<table>\n <tr>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/wechat-pay.png\" width=\"150\" alt=\"微信支付\"><br><b>微信支付</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/alipay.png\" width=\"150\" alt=\"支付宝\"><br><b>支付宝</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/buymeacoffee.png\" width=\"150\" alt=\"Buy Me a Coffee\"><br><b>Buy Me a Coffee</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/awarding/award.gif\" width=\"150\" alt=\"打赏\"><br><b>打赏鼓励</b></td>\n </tr>\n</table>\n\n## 开源协议\n\nMIT\n"}, "cfc2733483dc3b2284b287357f1da64fe0ce8db9": {"t": 1785758062.0289745, "n": 6583, "h": "3ec3021bf0482760", "c": "---\ntitle: dsclaude\ndescription: 面向非 Anthropic 后端的启动器工具集\n---\n\n[English](./) · **中文** · [GitHub](https://github.com/Agents365-ai/dsclaude)\n\n让 [Claude Code](https://claude.ai/code) 和 Claude Desktop 接入 DeepSeek、小米 MiMo 等第三方模型后端的小工具集。\n\n**作者:** [Agents365-ai](https://github.com/Agents365-ai) · [Bilibili](https://space.bilibili.com/441831884)\n\n---\n\n## 工具一览\n\n| 工具 | 作用 | 平台 | 后端 |\n|------|------|------|------|\n| **[dsclaude](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude)** | Claude Code CLI 启动器 | macOS / Linux | DeepSeek |\n| **[mmclaude](https://github.com/Agents365-ai/dsclaude/blob/main/mmclaude)** | Claude Code CLI 启动器 | macOS / Linux | 小米 MiMo |\n| **[dsclaude-desktop](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude-desktop)** | Claude Desktop GUI 配置器 | macOS | DeepSeek |\n| **[dsclaude-desktop.ps1](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude-desktop.ps1)** | Claude Desktop GUI 配置器 | Windows | DeepSeek |\n| **[skills/deepseek-vision](https://github.com/Agents365-ai/dsclaude/tree/main/skills/deepseek-vision)** | 视觉识别 skill(零依赖) | macOS / Linux | DashScope Qwen |\n| **[dsvision-mcp](https://github.com/Agents365-ai/dsclaude/blob/main/dsvision-mcp)** | 视觉识别 MCP 服务 | macOS / Linux | DashScope Qwen |\n\n---\n\n## macOS 快速开始\n\n```bash\ngit clone https://github.com/Agents365-ai/dsclaude.git\ncd dsclaude\nchmod +x dsclaude\n./dsclaude\n```\n\n---\n\n## dsclaude — Claude Code 接入 DeepSeek\n\n遵循 [DeepSeek Anthropic API](https://api-docs.deepseek.com/guides/anthropic_api) 指南。\n\n```bash\nexport DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 添加到 ~/.zshrc\n\ndsclaude # 默认 deepseek-v4-pro(完整推理)\ndsclaude fast # deepseek-v4-flash(更快更便宜)\ndsclaude long # 1M 上下文窗口\ndsclaude long fast # 1M + flash\n```\n\n自动设置 DeepSeek 推荐的环境变量(`ANTHROPIC_BASE_URL`、模型映射、`CLAUDE_CODE_EFFORT_LEVEL=max`),并在 `/model` 选择器中暴露备选模型。上下文窗口上限可通过 `DSCLAUDE_MAX_TOKENS` 覆盖,effort 级别通过 `DSCLAUDE_EFFORT` 覆盖。\n\n> 两个模型都原生支持 1M token,在 Claude Code 中需加 `[1m]` 后缀(如 `deepseek-v4-pro[1m]`),脚本已自动处理。\n\n---\n\n## mmclaude — Claude Code 接入小米 MiMo\n\n```bash\nexport MIMO_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 按量付费\n# 或\nexport MIMO_API_KEY=tp-xxxxxxxxxxxxxxxxxx # Token Plan\n\nmmclaude # 启动 mimo-v2.5-pro\nmmclaude update # git pull 拉取更新\n```\n\n按 key 前缀自动选择 base URL(`sk-*` → 公网,`tp-*` → Token Plan),可用 `MIMO_BASE_URL` 覆盖。所有模型槽位都指向 `mimo-v2.5-pro`,并自动 unset `ANTHROPIC_API_KEY`(避免遮蔽 bearer token)。\n\n---\n\n## dsclaude-desktop — Claude Desktop GUI 配置器\n\n一键配置 Claude Desktop **内置**的 Third-Party Inference 功能(Developer 菜单),预填 DeepSeek 参数并重启 App。\n\n### 前置条件\n\n1. 已安装 Claude Desktop([claude.ai/download](https://claude.ai/download))\n2. 已启用 Developer Mode(Help → Troubleshooting → Enable Developer Mode,一次即可)\n3. 已设置 `DEEPSEEK_API_KEY` 环境变量\n\n### 用法(macOS)\n\n```bash\nexport DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./dsclaude-desktop # 配置并重启\n./dsclaude-desktop -h # 帮助\n```\n\n脚本在 `~/Library/Application Support/Claude-3p/configLibrary/` 下生成配置 entry,将其设为 `appliedId`,然后重启 App。原本通过 GUI 添加的其他 entry 不受影响。\n\n### 模式切换\n\nClaude Desktop 启动选择器原生支持 Anthropic ↔ Gateway 切换,无需 `--revert`。在 App 内点头像 → Disconnect,下次启动时选另一个入口即可。\n\n> 唯一不可用的功能是经典 **Chat**(依赖 Anthropic 托管服务且不在 inference API 表面)。需要用 Chat 时切回 Anthropic 模式即可。\n\n### 用法(Windows)\n\n```powershell\n$env:DEEPSEEK_API_KEY = \"sk-xxxxxxxxxxxxxxxxxx\"\npwsh ./dsclaude-desktop.ps1\n```\n\n**无需手动启用 Developer Mode** —— 脚本会自动创建 `developer_settings.json`。\n\n配置目录:`%LOCALAPPDATA%\\Claude-3p\\configLibrary\\`(若为 Store/MSIX 安装,脚本还会额外写入沙箱路径 `LocalCache\\Roaming\\Claude-3p\\configLibrary\\` 作为后备)。\n\n已在 Windows 11 + Claude Desktop 1.7196(Windows Store, arm64)上实测通过。\n\n---\n\n## deepseek-vision skill — 视觉识别(零依赖方案)\n\n给纯文本模型(如 DeepSeek)补上\"看图\"能力的 skill。代理遇到图片时调 `analyze-image` 脚本,发给 Qwen3.6-Flash 识别后将描述返回主模型。\n\n```bash\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./skills/deepseek-vision/analyze-image /path/to/screenshot.png \"图里报的什么错?\"\n./skills/deepseek-vision/analyze-image https://example.com/diagram.png\n```\n\n任何加载 `SKILL.md` 的 agent(Claude Code、Cowork 等)都能用它。默认模型 `qwen3.6-flash`,可通过 `DSVISION_MODEL` 和 `DSVISION_BASE_URL` 切换。\n\n> **限制**:需文件路径或 URL,不支持拖拽/粘贴/「+ → Add files or photos」上传的图片。这类场景请用下方的 **dsvision-mcp**。\n\n---\n\n## dsvision-mcp — 视觉识别(MCP 方案)\n\n功能同上,但以 MCP 服务形式运行,绕过 Cowork 沙箱的两个限制:\n\n1. **网络出口管制** — skill 调 DashScope API 会被沙箱防火墙拦截,MCP 服务跑在沙箱外\n2. **内联图片** — 自动读取 `~/.claude/image-cache/` 中最新缓存,拖拽/粘贴/菜单上传均可正常工作(仅 macOS,Windows Cowork 不缓存内联图)\n\n### 安装\n\n```bash\npip3 install fastmcp requests\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 建议加到 ~/.zshrc\ncd /path/to/dsclaude && pwd # 记下绝对路径\n```\n\n然后根据当前模式,在对应的配置文件中添加 MCP 服务:\n\n| 模式 | 配置文件 |\n|------|----------|\n| 3P/Gateway(通过 `dsclaude-desktop` 使用 DeepSeek) | `~/Library/Application Support/Claude-3p/claude_desktop_config.json` |\n| 标准 Anthropic 模式 | `~/Library/Application Support/Claude/claude_desktop_config.json` |\n\n```json\n{\n \"mcpServers\": {\n \"dsvision\": {\n \"command\": \"/绝对/路径/dsclaude/dsvision-mcp\"\n }\n }\n}\n```\n\n重启 Claude Desktop 后,`analyze_image` 工具自动出现。\n\n### 用法\n\n```\nanalyze_image() # 自动检测最新缓存图片\nanalyze_image(image_path=\"/绝对/路径/foo.png\")\nanalyze_image(focus=\"图里报的什么错?\") # 自定义 prompt\n```\n\n### 常见问题\n\n| 现象 | 排查方向 |\n|------|----------|\n| 工具不显示 | 配置文件路径选错 / JSON 格式错误(用 `python3 -m json.tool` 校验) |\n| 工具报错 | `DASHSCOPE_API_KEY` 未设置 |\n| `ModuleNotFoundError` | 用 `pip3` 而非 `pip` |\n| 找不到图片 | 传绝对路径,或检查 `~/.claude/image-cache/` 是否存在 |\n\n### skill vs MCP 怎么选\n\n| 场景 | 推荐 |\n|------|------|\n| Claude Code (CLI),给明确路径 | `skills/deepseek-vision`(零依赖) |\n| Cowork / Desktop,拖拽/粘贴内联图 | `dsvision-mcp`(唯一能用的) |\n| Cowork,给明确路径,不介意沙箱限制 | 两者均可 |\n\n---\n\n## 社区\n\n- **Discord:** <https://discord.gg/79JF5Atuk>\n- **微信:** 扫描下方二维码\n\n<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/agents365ai_wechat_1.png\" width=\"200\" alt=\"微信交流群\">\n</p>\n\n## 赞赏支持\n\n如果这些脚本为你节省了时间,欢迎支持作者:\n\n<table>\n <tr>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/wechat-pay.png\" width=\"150\" alt=\"微信支付\"><br><b>微信支付</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/alipay.png\" width=\"150\" alt=\"支付宝\"><br><b>支付宝</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/buymeacoffee.png\" width=\"150\" alt=\"Buy Me a Coffee\"><br><b>Buy Me a Coffee</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/awarding/award.gif\" width=\"150\" alt=\"打赏\"><br><b>打赏鼓励</b></td>\n </tr>\n</table>\n\n## 开源协议\n\nMIT\n"}}, "README.md": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785595191.9534256, "n": 31394, "h": "c49d6c68ebd22a04", "c": "# dsclaude — Claude Code & Claude Desktop launchers for alternative backends\n\n[中文文档](README_CN.md)\n\nA collection of launchers and configurators that point [Claude Code](https://claude.ai/code) and Claude Desktop at third-party model backends (DeepSeek, MiMo, Qwen, GLM, Kimi, Ark, LongCat, MiniMax, TokenHub, SiliconFlow, etc.).\n\n---\n\n## Tools\n\n| Tool | What it does | Platform | Backend |\n| ------ | ------------- | ---------- | --------- |\n| **[dsclaude](dsclaude)** | Claude Code CLI launcher | macOS / Linux | DeepSeek |\n| **[dsclaude.ps1](dsclaude.ps1)** | Claude Code CLI launcher | Windows | DeepSeek |\n| **[mmclaude](mmclaude)** | Claude Code CLI launcher | macOS / Linux | Xiaomi MiMo |\n| **[mmclaude.ps1](mmclaude.ps1)** | Claude Code CLI launcher | Windows | Xiaomi MiMo |\n| **[qwclaude](qwclaude)** | Claude Code CLI launcher | macOS / Linux | Alibaba Cloud Bailian (Qwen) |\n| **[qwclaude.ps1](qwclaude.ps1)** | Claude Code CLI launcher | Windows | Alibaba Cloud Bailian (Qwen) |\n| **[glmclaude](glmclaude)** | Claude Code CLI launcher | macOS / Linux | ZhipuAI GLM |\n| **[glmclaude.ps1](glmclaude.ps1)** | Claude Code CLI launcher | Windows | ZhipuAI GLM |\n| **[kmclaude](kmclaude)** | Claude Code CLI launcher | macOS / Linux | Moonshot AI Kimi |\n| **[kmclaude.ps1](kmclaude.ps1)** | Claude Code CLI launcher | Windows | Moonshot AI Kimi |\n| **[arkclaude](arkclaude)** | Claude Code CLI launcher | macOS / Linux | Volcengine Ark (doubao/Kimi/DeepSeek/GLM…) |\n| **[arkclaude.ps1](arkclaude.ps1)** | Claude Code CLI launcher | Windows | Volcengine Ark (doubao/Kimi/DeepSeek/GLM…) |\n| **[lcclaude](lcclaude)** | Claude Code CLI launcher | macOS / Linux | Meituan LongCat |\n| **[lcclaude.ps1](lcclaude.ps1)** | Claude Code CLI launcher | Windows | Meituan LongCat |\n| **[mxclaude](mxclaude)** | Claude Code CLI launcher | macOS / Linux | MiniMax |\n| **[mxclaude.ps1](mxclaude.ps1)** | Claude Code CLI launcher | Windows | MiniMax |\n| **[hyclaude](hyclaude)** | Claude Code CLI launcher | macOS / Linux | Tencent TokenHub (HY3/DeepSeek/Kimi/GLM…) |\n| **[hyclaude.ps1](hyclaude.ps1)** | Claude Code CLI launcher | Windows | Tencent TokenHub (HY3/DeepSeek/Kimi/GLM…) |\n| **[sfclaude](sfclaude)** | Claude Code CLI launcher | macOS / Linux | SiliconFlow (DeepSeek/Kimi/GLM/Qwen/Yi…) |\n| **[sfclaude.ps1](sfclaude.ps1)** | Claude Code CLI launcher | Windows | SiliconFlow (DeepSeek/Kimi/GLM/Qwen/Yi…) |\n| **[xclaude](xclaude)** | Unified auto-detect launcher | macOS / Linux | Any (auto-detects from API keys) |\n| **[dsclaude-desktop](dsclaude-desktop)** | Claude Desktop GUI configurator | macOS | DeepSeek |\n| **[dsclaude-desktop.ps1](dsclaude-desktop.ps1)** | Claude Desktop GUI configurator | Windows | DeepSeek |\n| **[mmclaude-desktop](mmclaude-desktop)** | Claude Desktop GUI configurator | macOS | Xiaomi MiMo |\n| **[mmclaude-desktop.ps1](mmclaude-desktop.ps1)** | Claude Desktop GUI configurator | Windows | Xiaomi MiMo |\n| **[qwclaude-desktop](qwclaude-desktop)** | Claude Desktop GUI configurator | macOS | Alibaba Cloud Bailian (Qwen) |\n| **[qwclaude-desktop.ps1](qwclaude-desktop.ps1)** | Claude Desktop GUI configurator | Windows | Alibaba Cloud Bailian (Qwen) |\n| **[glmclaude-desktop](glmclaude-desktop)** | Claude Desktop GUI configurator | macOS | ZhipuAI GLM |\n| **[glmclaude-desktop.ps1](glmclaude-desktop.ps1)** | Claude Desktop GUI configurator | Windows | ZhipuAI GLM |\n| **[kmclaude-desktop](kmclaude-desktop)** | Claude Desktop GUI configurator | macOS | Moonshot AI Kimi |\n| **[kmclaude-desktop.ps1](kmclaude-desktop.ps1)** | Claude Desktop GUI configurator | Windows | Moonshot AI Kimi |\n| **[arkclaude-desktop](arkclaude-desktop)** | Claude Desktop GUI configurator | macOS | Volcengine Ark |\n| **[arkclaude-desktop.ps1](arkclaude-desktop.ps1)** | Claude Desktop GUI configurator | Windows | Volcengine Ark |\n| **[lcclaude-desktop](lcclaude-desktop)** | Claude Desktop GUI configurator | macOS | Meituan LongCat |\n| **[lcclaude-desktop.ps1](lcclaude-desktop.ps1)** | Claude Desktop GUI configurator | Windows | Meituan LongCat |\n| **[mxclaude-desktop](mxclaude-desktop)** | Claude Desktop GUI configurator | macOS | MiniMax |\n| **[mxclaude-desktop.ps1](mxclaude-desktop.ps1)** | Claude Desktop GUI configurator | Windows | MiniMax |\n| **[hyclaude-desktop](hyclaude-desktop)** | Claude Desktop GUI configurator | macOS | Tencent TokenHub |\n| **[hyclaude-desktop.ps1](hyclaude-desktop.ps1)** | Claude Desktop GUI configurator | Windows | Tencent TokenHub |\n| **[sfclaude-desktop](sfclaude-desktop)** | Claude Desktop GUI configurator | macOS | SiliconFlow |\n| **[sfclaude-desktop.ps1](sfclaude-desktop.ps1)** | Claude Desktop GUI configurator | Windows | SiliconFlow |\n| **[skills/deepseek-vision](skills/deepseek-vision/)** | Vision skill (zero deps) | macOS / Linux | DashScope Qwen |\n| **[dsvision-mcp](dsvision-mcp)** | Vision MCP server | macOS / Linux | DashScope Qwen |\n\n---\n\n## How it works\n\n\n\nScript-logic overview: the installer, the `xclaude` auto-detect dispatcher, the provider CLI launchers, the Claude Desktop configurators, and the Codex bridge — all sharing `lib/common.sh`. The PNG has the draw.io XML embedded, so opening it in [draw.io](https://app.diagrams.net) recovers the editable diagram ([source](docs/xxclaude-logic.drawio) · [中文版](docs/xxclaude-logic-cn.drawio.png)).\n\n---\n\n## Quick start on macOS\n\n```bash\n# One-line install (recommended):\ncurl -fsSL https://raw.githubusercontent.com/Agents365-ai/dsclaude/main/install.sh | bash\n\n# Or user install (no sudo):\ncurl -fsSL https://raw.githubusercontent.com/Agents365-ai/dsclaude/main/install.sh | bash -s -- --user\n\n# Or manual:\ngit clone https://github.com/Agents365-ai/dsclaude.git\ncd dsclaude\nchmod +x xclaude\n./xclaude\n```\n\n## Quick start on Windows\n\n```powershell\n# One-line install (PowerShell as admin recommended):\nirm https://raw.githubusercontent.com/Agents365-ai/dsclaude/main/install.ps1 | iex\n\n# Install with auto-PATH:\nirm https://raw.githubusercontent.com/Agents365-ai/dsclaude/main/install.ps1 | iex -AddToPath\n\n# Then launch:\npwsh -File xclaude.ps1\n```\n\n---\n\n## xclaude — Unified auto-detect launcher\n\nDon't remember which script to run? `xclaude` auto-detects your API key and delegates to the right backend.\n\n```bash\n# Set any one of these in your ~/.zshrc:\nexport DEEPSEEK_API_KEY=sk-... # → dsclaude\nexport GLM_API_KEY=... # → glmclaude\nexport KIMI_API_KEY=sk-... # → kmclaude\nexport ARK_API_KEY=... # → arkclaude\n# ... or any other supported key\n\nxclaude # auto-detect and launch\nxclaude fast # ...with fast/flash tier\nxclaude long effort max # ...with 1M context + max effort\nxclaude kimi # forwarded: on Ark → kimi model, etc.\n```\n\nAll positional args (model aliases, `fast`, `long`, `effort`, etc.) are forwarded to the underlying launcher. If multiple keys are set, the first found wins; set `XCLAUDE_PREFER=dsclaude` to force a specific provider.\n\n---\n\n## dsclaude — Claude Code on DeepSeek\n\nFollows the [DeepSeek Anthropic API](https://api-docs.deepseek.com/guides/anthropic_api) guide.\n\n```bash\nexport DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxx # add to ~/.zshrc\n\ndsclaude # default: deepseek-v4-pro (full reasoning)\ndsclaude fast # deepseek-v4-flash (cheaper / faster)\ndsclaude long # request 1M context window\ndsclaude long fast # 1M + flash\n```\n\nSets the DeepSeek-recommended env vars (`ANTHROPIC_BASE_URL`, model mappings, `CLAUDE_CODE_EFFORT_LEVEL=max`), and exposes the alternate model in Claude Code's `/model` picker. Override context window via `DSCLAUDE_MAX_TOKENS` and effort via `DSCLAUDE_EFFORT`.\n\n> Both models natively support 1M-token context. The `[1m]` suffix (e.g. `deepseek-v4-pro[1m]`) is required in Claude Code — `dsclaude` sets it automatically.\n>\n> Windows (PowerShell 7+): `pwsh -File ./dsclaude.ps1` (same flags).\n\n---\n\n## mmclaude — Claude Code on Xiaomi MiMo\n\n```bash\nexport MIMO_API_KEY=sk-xxxxxxxxxxxxxxxxxx # pay-as-you-go\n# or\nexport MIMO_API_KEY=tp-xxxxxxxxxxxxxxxxxx # Token Plan\n\nmmclaude # start on mimo-v2.5-pro\nmmclaude fast # start on mimo-v2.5 (cheaper / faster flash tier)\nmmclaude update # git pull\n```\n\nAuto-detects base URL from the key prefix (`sk-*` → public, `tp-*` → Token Plan); override with `MIMO_BASE_URL`. Main/opus/sonnet slots run `mimo-v2.5-pro` while the haiku and subagent tiers run `mimo-v2.5` (flash); `mmclaude fast` flips the main model to flash, and the other tier is exposed in the `/model` picker for mid-session switching. Unsets `ANTHROPIC_API_KEY` (per MiMo docs). Override the tiers with `MIMO_MODEL` / `MIMO_FLASH_MODEL`.\n\n> Windows (PowerShell 7+): `pwsh -File ./mmclaude.ps1` (same flags).\n\n---\n\n## qwclaude — Claude Code on Alibaba Cloud Bailian (Qwen)\n\n```bash\n# One key per plan — each comes from a different Bailian console entry:\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx # pay-as-you-go\nexport DASHSCOPE_CP_API_KEY=sk-xxxxxxxxxxxxxxxxxx # Coding Plan\nexport DASHSCOPE_TP_API_KEY=sk-xxxxxxxxxxxxxxxxxx # Token Plan team edition\n\n# macOS / Linux — three model tiers\nqwclaude # pay-as-you-go, qwen3.7-max (Beijing) → DASHSCOPE_API_KEY\nqwclaude plus # qwen3.7-plus (balanced, ~1/6 cost of max)\nqwclaude max # explicit qwen3.7-max\nqwclaude fast # qwen3.6-flash as the main model\nqwclaude intl # pay-as-you-go on the Singapore endpoint\nqwclaude coding # Coding Plan (qwen3.7-plus recommended) → DASHSCOPE_CP_API_KEY\nqwclaude coding plus # Coding Plan, qwen3.7-plus (default)\nqwclaude coding fast # Coding Plan, qwen3.6-plus\nqwclaude token # Token Plan (qwen3.7-max) → DASHSCOPE_TP_API_KEY\nqwclaude token plus # Token Plan, qwen3.7-plus\nqwclaude update # git pull\n\n# Windows (PowerShell 7+)\npwsh -File ./qwclaude.ps1 coding\n```\n\nPicks the base URL, model lineup, and API-key variable per billing plan and model tier. Three model tiers:\n\n| Tier | Pay-as-you-go & Token Plan | Coding Plan |\n| ------ | --------------------------- | ------------- |\n| **max** (default) | `qwen3.7-max` (flagship) | N/A |\n| **plus** | `qwen3.7-plus` (balanced, ~1/6 cost) | `qwen3.7-plus` (recommended) |\n| **flash** (subagent/haiku) | `qwen3.6-flash` | `qwen3.6-plus` |\n\nMain/opus/sonnet slots run the selected tier (default `qwen3.7-max`) while the haiku + subagent tiers always use the flash model. `fast` flips the main model to flash; `plus` flips to qwen3.7-plus. The other tier is exposed in the `/model` picker for mid-session switching. Sets `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` and unsets `ANTHROPIC_API_KEY` to keep traffic on Bailian. Override via `QWEN_PLAN` / `QWEN_REGION` / `QWEN_MODEL` / `QWEN_PLUS_MODEL` / `QWEN_FLASH_MODEL` / `QWEN_BASE_URL`.\n\n> The Windows port (`qwclaude.ps1`) requires PowerShell 7+ (`winget install Microsoft.PowerShell`) — run it with `pwsh -File`.\n\n---\n\n## glmclaude — Claude Code on ZhipuAI GLM\n\nFollows ZhipuAI's Anthropic-compatible API.\n\n```bash\nexport GLM_API_KEY=your_zhipu_api_key # add to ~/.zshrc\n# Get your key at: https://open.bigmodel.cn/usercenter/apikeys\n\nglmclaude # default: glm-5.2 (full reasoning)\nglmclaude fast # glm-4.7 (cheaper / faster)\nglmclaude update # git pull\n```\n\nSets the ZhipuAI-recommended env vars (`ANTHROPIC_BASE_URL`, model mappings), and exposes the alternate model in Claude Code's `/model` picker. Main/opus/sonnet slots run `glm-5.2` while the haiku and subagent tiers run `glm-4.7`; `glmclaude fast` flips the main model to flash, and the other tier is exposed in the `/model` picker for mid-session switching.\n\nBy default uses the China endpoint (`https://open.bigmodel.cn/api/anthropic`). For the international endpoint, set `GLM_BASE_URL`:\n\n```bash\nexport GLM_BASE_URL=https://api.z.ai/api/anthropic\nglmclaude\n```\n\nOverride the tiers with `GLM_MODEL` / `GLM_FLASH_MODEL`.\n\n> Windows (PowerShell 7+): `pwsh -File ./glmclaude.ps1` (same flags).\n\n---\n\n## kmclaude — Claude Code on Moonshot AI Kimi\n\n```bash\nexport KIMI_API_KEY=sk-xxxxxxxxxxxxxxxxxx # add to ~/.zshrc\n# Get your key at: https://platform.moonshot.cn/console/api-keys\n\nkmclaude # start on kimi-k3 (flagship)\nkmclaude fast # start on kimi-k2.5 (cheaper / faster tier)\nkmclaude update # git pull\n```\n\nUses the official Kimi Anthropic-compatible endpoint (`https://api.moonshot.cn/anthropic`). Main/opus/sonnet slots run `kimi-k3` while the haiku and subagent tiers run `kimi-k2.5`; `kmclaude fast` flips the main model to k2.5, and the other tier is exposed in the `/model` picker for mid-session switching. Unsets `ANTHROPIC_API_KEY` to avoid credential shadowing. Override the tiers with `KIMI_MODEL` / `KIMI_FLASH_MODEL` and the base URL with `KIMI_BASE_URL`.\n\n> Windows (PowerShell 7+): `pwsh -File ./kmclaude.ps1` (same flags).\n\n---\n\n## dsclaude-desktop — Claude Desktop GUI configurator\n\nOne-command configurator for Claude Desktop's built-in **Third-Party Inference** feature (Developer menu), pre-filled for DeepSeek.\n\n### Prerequisites\n\n1. Claude Desktop installed ([claude.ai/download](https://claude.ai/download))\n2. Developer Mode enabled (Help → Troubleshooting → Enable Developer Mode, once)\n3. `DEEPSEEK_API_KEY` environment variable set\n\n### Usage\n\n```bash\nexport DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./dsclaude-desktop # configure and restart\n./dsclaude-desktop -h # help\n```\n\nGenerates an entry under `~/Library/Application Support/Claude-3p/configLibrary/`, sets it as `appliedId` in `_meta.json`, then restarts the app. Existing GUI-added entries are preserved.\n\n### Switching modes\n\nClaude Desktop's launch chooser handles Anthropic ↔ Gateway switching natively — no `--revert` flag. Click your profile → **Disconnect** (or sign out), then pick the other option at next launch.\n\n> Classic **Chat** (claude.ai-style) is unavailable in Gateway mode — it depends on Anthropic-hosted features not exposed via the inference API. Switch back to Anthropic mode to use it.\n\n### Windows\n\n```powershell\n$env:DEEPSEEK_API_KEY = \"sk-xxxxxxxxxxxxxxxxxx\"\npwsh ./dsclaude-desktop.ps1\n```\n\nWrites to `%APPDATA%\\Claude-3p\\configLibrary\\`. > Untested by the maintainer — please [open an issue](https://github.com/Agents365-ai/dsclaude/issues) if anything misbehaves.\n\n---\nPrerequisites: Claude Desktop installed (Store or standard), DeepSeek API key. Unlike macOS, Developer Mode is **auto-enabled** by the script — no manual GUI toggle needed.\n\nConfig path: `%LOCALAPPDATA%\\Claude-3p\\configLibrary\\` (for Store/MSIX installs, the script also writes to the sandboxed package path as a fallback).\n\nTested on Windows 11 with Claude Desktop 1.7196 (Windows Store, arm64).\n\n---\n\n## mmclaude-desktop — Claude Desktop on Xiaomi MiMo\n\nSame configurator as `dsclaude-desktop`, pre-filled for Xiaomi MiMo. Reads `MIMO_API_KEY` and auto-detects the base URL from the key prefix (`tp-*` → Token Plan, else pay-as-you-go; override with `MIMO_BASE_URL`). Configures `mimo-v2.5-pro` + `mimo-v2.5`.\n\n```bash\nexport MIMO_API_KEY=sk-xxxxxxxxxxxxxxxxxx # or tp-... for Token Plan\n./mmclaude-desktop # configure and restart (macOS)\n./mmclaude-desktop -h # help\n\n# Windows (PowerShell)\n$env:MIMO_API_KEY = \"sk-xxxxxxxxxxxxxxxxxx\"\npwsh ./mmclaude-desktop.ps1\n```\n\n---\n\n## qwclaude-desktop — Claude Desktop on Alibaba Cloud Bailian (Qwen)\n\nSame configurator, with per-plan base URL, models, and key variable. Pay-as-you-go (`DASHSCOPE_API_KEY`) and Token Plan (`DASHSCOPE_TP_API_KEY`) default to `qwen3.7-max` + `qwen3.6-flash`; Coding Plan (`DASHSCOPE_CP_API_KEY`) configures `qwen3.7-plus` + `qwen3.6-plus`. Add `plus` to use qwen3.7-plus for any plan.\n\n```bash\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx # pay-as-you-go\nexport DASHSCOPE_CP_API_KEY=sk-xxxxxxxxxxxxxxxxxx # Coding Plan\nexport DASHSCOPE_TP_API_KEY=sk-xxxxxxxxxxxxxxxxxx # Token Plan\n\n./qwclaude-desktop # pay-as-you-go (Beijing), qwen3.7-max, then restart\n./qwclaude-desktop plus # pay-as-you-go, qwen3.7-plus\n./qwclaude-desktop intl # pay-as-you-go, Singapore endpoint\n./qwclaude-desktop coding # Coding Plan (qwen3.7-plus)\n./qwclaude-desktop token # Token Plan, qwen3.7-max\n./qwclaude-desktop token plus # Token Plan, qwen3.7-plus\n\n# Windows (PowerShell)\npwsh ./qwclaude-desktop.ps1 -Plan coding\npwsh ./qwclaude-desktop.ps1 -Plan token -ModelTier plus\n```\n\n> The `.ps1` Windows ports mirror `dsclaude-desktop.ps1` and are **untested by the maintainer** — please [open an issue](https://github.com/Agents365-ai/dsclaude/issues) if anything misbehaves. Both configurators set `unstableDisableModelVerification` so Claude Desktop accepts the non-Anthropic model names, and (like `dsclaude-desktop`) disable Chat mode while the gateway is active.\n\n---\n\n## glmclaude-desktop — Claude Desktop on ZhipuAI GLM\n\nSame configurator, pre-filled for ZhipuAI GLM. Reads `GLM_API_KEY`. Configures `glm-5.2` + `glm-4.7`.\n\n```bash\nexport GLM_API_KEY=your_zhipu_api_key\n./glmclaude-desktop # configure and restart (macOS)\n./glmclaude-desktop -h # help\n\n# Windows (PowerShell)\n$env:GLM_API_KEY = \"your_zhipu_api_key\"\npwsh ./glmclaude-desktop.ps1\n```\n\nOverride the base URL with `GLM_BASE_URL` (default: `https://open.bigmodel.cn/api/anthropic`).\n\n---\n\n## kmclaude-desktop — Claude Desktop on Moonshot AI Kimi\n\nSame configurator, pre-filled for Moonshot Kimi. Reads `KIMI_API_KEY`. Configures `kimi-k3` + `kimi-k2.5`.\n\n```bash\nexport KIMI_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./kmclaude-desktop # configure and restart (macOS)\n./kmclaude-desktop -h # help\n\n# Windows (PowerShell)\n$env:KIMI_API_KEY = \"sk-xxxxxxxxxxxxxxxxxx\"\npwsh ./kmclaude-desktop.ps1\n```\n\nOverride the base URL with `KIMI_BASE_URL` (default: `https://api.moonshot.cn/anthropic`).\n\n---\n\n## arkclaude — Claude Code on Volcengine Ark (Coding Plan)\n\nVolcengine Ark's Coding Plan aggregates multiple model families under one subscription — doubao, Kimi, DeepSeek, GLM, MiniMax, and more. One API key, one endpoint, many models.\n\n```bash\nexport ARK_API_KEY=your_ark_api_key # add to ~/.zshrc\n# Get your key at: https://console.volcengine.com/ark\n\n# Three doubao tiers + provider aliases for quick model switching\narkclaude # doubao-seed-2.0-code (code specialist, default)\narkclaude plus # doubao-seed-2.0-pro (balanced flagship)\narkclaude fast # doubao-seed-2.0-lite (cheap / fast)\narkclaude kimi # kimi-k2.7-code (Kimi code model)\narkclaude kimi-pro # kimi-k2.6\narkclaude deepseek # deepseek-v4-pro\narkclaude deepseek-flash # deepseek-v4-flash\narkclaude glm # glm-5.2\narkclaude minimax # minimax-m2.7\narkclaude update # git pull\n```\n\nUses the Ark Coding Plan endpoint (`https://ark.cn-beijing.volces.com/api/coding`). Main/opus/sonnet slots run the chosen model while the haiku + subagent tiers always use the cheapest model in the same family (or `doubao-seed-2.0-lite` as fallback). The /model picker exposes a smart alternate based on your selection — Pro ↔ Code when using doubao, K2.6 ↔ K2.7-code when using Kimi, etc. Sets `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` and unsets `ANTHROPIC_API_KEY` to keep traffic on Ark. Override via `ARK_MODEL` / `ARK_PLUS_MODEL` / `ARK_FLASH_MODEL` / `ARK_BASE_URL`.\n\n> Windows (PowerShell 7+): `pwsh -File ./arkclaude.ps1` (same flags).\n\n---\n\n## arkclaude-desktop — Claude Desktop on Volcengine Ark\n\nSame configurator, pre-filled for Ark Coding Plan. Reads `ARK_API_KEY`. Supports all model aliases for picking the inference model.\n\n```bash\nexport ARK_API_KEY=your_ark_api_key\n./arkclaude-desktop # configure with doubao-seed-2.0-code and restart\n./arkclaude-desktop plus # doubao-seed-2.0-pro\n./arkclaude-desktop kimi # kimi-k2.7-code\n./arkclaude-desktop deepseek # deepseek-v4-pro\n./arkclaude-desktop glm # glm-5.2\n./arkclaude-desktop minimax # minimax-m2.7\n./arkclaude-desktop -h # help\n\n# Windows (PowerShell)\n$env:ARK_API_KEY = \"your_ark_api_key\"\npwsh ./arkclaude-desktop.ps1 -ModelTier kimi\n```\n\nOverride the base URL with `ARK_BASE_URL` (default: `https://ark.cn-beijing.volces.com/api/coding`).\n\n---\n\n## lcclaude — Claude Code on Meituan LongCat\n\nLongCat-2.0 is a 1.6T-param MoE model built entirely on Chinese-manufactured compute. It ranked #2 globally in Claude Code monthly call volume on OpenRouter. **Free during public beta** — 500K tokens/day.\n\n```bash\nexport LONGCAT_API_KEY=lc-xxxxxxxxxxxxxxxxxx # add to ~/.zshrc\n# Get your free key at: https://longcat.chat/platform\n\nlcclaude # LongCat-2.0 (1M context, flagship)\nlcclaude fast # LongCat-Flash-Chat (cheaper / faster)\nlcclaude think # LongCat-Flash-Thinking (deep reasoning)\nlcclaude update # git pull\n```\n\nUses the LongCat Anthropic-compatible endpoint (`https://api.longcat.chat/anthropic`). Main/opus/sonnet slots run the chosen model while the haiku + subagent tiers use `LongCat-Flash-Chat`. The `/model` picker exposes the alternate tier. Override via `LONGCAT_MODEL` / `LONGCAT_FLASH_MODEL` / `LONGCAT_THINK_MODEL` / `LONGCAT_BASE_URL`.\n\n> Windows (PowerShell 7+): `pwsh -File ./lcclaude.ps1` (same flags).\n\n---\n\n## lcclaude-desktop — Claude Desktop on Meituan LongCat\n\nSame configurator, pre-filled for LongCat. Reads `LONGCAT_API_KEY`. Configures `LongCat-2.0` + `LongCat-Flash-Chat`.\n\n```bash\nexport LONGCAT_API_KEY=lc-xxxxxxxxxxxxxxxxxx\n./lcclaude-desktop # configure and restart (macOS)\n./lcclaude-desktop -h # help\n\n# Windows (PowerShell)\n$env:LONGCAT_API_KEY = \"lc-xxxxxxxxxxxxxxxxxx\"\npwsh ./lcclaude-desktop.ps1\n```\n\nOverride the base URL with `LONGCAT_BASE_URL` (default: `https://api.longcat.chat/anthropic`).\n\n---\n\n## mxclaude — Claude Code on MiniMax\n\nMiniMax-M3 is a 1M-context flagship model optimized for agentic reasoning, tool use, and coding. **Requires a Coding Plan (Token Plan) API key** — not pay-as-you-go.\n\n```bash\nexport MINIMAX_API_KEY=your_minimax_api_key # add to ~/.zshrc\n# Get your key at: https://platform.minimaxi.com\n\nmxclaude # MiniMax-M3 (1M context, flagship)\nmxclaude fast # MiniMax-M2.5 (cheaper / faster)\nmxclaude long # request 1M context window\nmxclaude effort max # set reasoning effort (low|medium|high|xhigh|max)\nmxclaude update # git pull\n```\n\nUses the MiniMax Anthropic-compatible endpoint (default: `https://api.minimaxi.com/anthropic` for China; override with `MINIMAX_BASE_URL` for international `https://api.minimax.io/anthropic`). Main/opus/sonnet slots run the chosen model while the haiku + subagent tiers use `MiniMax-M2.5`. The `/model` picker exposes the alternate tier. Override via `MINIMAX_MODEL` / `MINIMAX_FLASH_MODEL` / `MINIMAX_BASE_URL` / `MINIMAX_CTX` / `MINIMAX_OUTPUT` / `MINIMAX_EFFORT`.\n\n> Windows (PowerShell 7+): `pwsh -File ./mxclaude.ps1` (same flags).\n\n---\n\n## mxclaude-desktop — Claude Desktop on MiniMax\n\nSame configurator, pre-filled for MiniMax. Reads `MINIMAX_API_KEY`. Configures `MiniMax-M3` + `MiniMax-M2.5`.\n\n```bash\nexport MINIMAX_API_KEY=your_minimax_api_key\n./mxclaude-desktop # configure and restart (macOS)\n./mxclaude-desktop -h # help\n\n# Windows (PowerShell)\n$env:MINIMAX_API_KEY = \"your_minimax_api_key\"\npwsh ./mxclaude-desktop.ps1\n```\n\nOverride the base URL with `MINIMAX_BASE_URL` (default: `https://api.minimaxi.com/anthropic`; international: `https://api.minimax.io/anthropic`).\n\n---\n\n## hyclaude — Claude Code on Tencent TokenHub\n\nTencent TokenHub is a multi-model aggregator — one subscription gives access to Hunyuan (HY3), DeepSeek, GLM, Kimi, MiniMax, Qwen, and more.\n\n```bash\nexport HY_API_KEY=your_api_key # add to ~/.zshrc\n# Get your key at: https://cloud.tencent.com/product/lkeap\n\nhyclaude # hy3-preview (Tencent default)\nhyclaude fast # hy-mt2-lite (cheap / fast)\nhyclaude deepseek # deepseek-v4-pro\nhyclaude kimi # kimi-k2.7-code\nhyclaude glm # glm-5.2\nhyclaude minimax # minimax-m3\nhyclaude qwen # qwen3.5-plus\nhyclaude long # request max context window\nhyclaude effort max # set reasoning effort (low|medium|high|xhigh|max)\nhyclaude update # git pull\n```\n\nUses the TokenHub Anthropic-compatible endpoint (default: `https://api.lkeap.cloud.tencent.com/plan/anthropic`). Main/opus/sonnet slots run the chosen model while haiku + subagent tiers use `hy-mt2-lite` (or a same-family flash model for non-HY selections). The `/model` picker exposes a smart alternate. Override via `HY_MODEL` / `HY_FLASH_MODEL` / `HY_BASE_URL` / `HY_CTX` / `HY_OUTPUT` / `HY_EFFORT`.\n\n> Windows (PowerShell 7+): `pwsh -File ./hyclaude.ps1` (same flags).\n\n---\n\n## hyclaude-desktop — Claude Desktop on Tencent TokenHub\n\nSame configurator, pre-filled for TokenHub. Reads `HY_API_KEY`. Supports model aliases for the backend model.\n\n```bash\nexport HY_API_KEY=your_api_key\n./hyclaude-desktop # configure with hy3-preview and restart\n./hyclaude-desktop kimi # kimi-k2.7-code\n./hyclaude-desktop deepseek # deepseek-v4-pro\n./hyclaude-desktop glm # glm-5.2\n./hyclaude-desktop minimax # minimax-m3\n./hyclaude-desktop qwen # qwen3.5-plus\n./hyclaude-desktop -h # help\n\n# Windows (PowerShell)\n$env:HY_API_KEY = \"your_api_key\"\npwsh ./hyclaude-desktop.ps1 -ModelTier kimi\n```\n\nOverride the base URL with `HY_BASE_URL` (default: `https://api.lkeap.cloud.tencent.com/plan/anthropic`).\n\n---\n\n## sfclaude — Claude Code on SiliconFlow\n\nSiliconFlow (硅基流动) is a multi-model platform aggregating DeepSeek, Kimi, GLM, MiniMax, Qwen, Yi, and more. Models use the `provider/Model-Name` convention (e.g. `deepseek-ai/DeepSeek-V4-PRO`).\n\n```bash\nexport SF_API_KEY=sk-xxxxxxxxxxxxxxxxxx # add to ~/.zshrc\n# Get your key at: https://cloud.siliconflow.cn/account/ak\n\nsfclaude # deepseek-ai/DeepSeek-V4-PRO (default)\nsfclaude fast # deepseek-ai/DeepSeek-V3 (cheaper)\nsfclaude kimi # moonshotai/Kimi-K2-Instruct-0905\nsfclaude glm # Pro/zai-org/GLM-5\nsfclaude minimax # Pro/MiniMaxAI/MiniMax-M2.5\nsfclaude qwen # Qwen/Qwen2.5-Coder\nsfclaude yi # 01-ai/Yi-1.5\nsfclaude r1 # deepseek-ai/DeepSeek-R1 (deep reasoning)\nsfclaude long # request max context window\nsfclaude effort max # set reasoning effort (low|medium|high|xhigh|max)\nsfclaude update # git pull\n```\n\nUses the SiliconFlow Anthropic-compatible endpoint (`https://api.siliconflow.cn/`). Main/opus/sonnet slots run the chosen model while haiku + subagent tiers use `deepseek-ai/DeepSeek-V3`. Override via `SF_MODEL` / `SF_FLASH_MODEL` / `SF_BASE_URL` / `SF_CTX` / `SF_OUTPUT` / `SF_EFFORT`.\n\n> Windows (PowerShell 7+): `pwsh -File ./sfclaude.ps1` (same flags).\n\n---\n\n## sfclaude-desktop — Claude Desktop on SiliconFlow\n\nSame configurator, pre-filled for SiliconFlow. Reads `SF_API_KEY`. Supports model aliases.\n\n```bash\nexport SF_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./sfclaude-desktop # deepseek-ai/DeepSeek-V4-PRO and restart\n./sfclaude-desktop kimi # moonshotai/Kimi-K2-Instruct-0905\n./sfclaude-desktop r1 # deepseek-ai/DeepSeek-R1\n./sfclaude-desktop -h # help\n\n# Windows (PowerShell)\n$env:SF_API_KEY = \"sk-xxxxxxxxxxxxxxxxxx\"\npwsh ./sfclaude-desktop.ps1 -ModelTier kimi\n```\n\n---\n\n## deepseek-vision skill — Vision (zero-dependency)\n\nGives text-only agents (like DeepSeek) the ability to \"see\" images. When the agent encounters an image, it calls `analyze-image`, which sends it to Qwen3.6-Flash and returns a text description.\n\n```bash\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./skills/deepseek-vision/analyze-image /path/to/screenshot.png \"What error is shown?\"\n./skills/deepseek-vision/analyze-image https://example.com/diagram.png\n```\n\nWorks with any agent that loads `SKILL.md` (Claude Code, Cowork, etc.). Default model `qwen3.6-flash`; override via `DSVISION_MODEL` and `DSVISION_BASE_URL`.\n\n> **Limitation**: requires a file path or URL — inline images (drag-drop, paste, \"+ → Add files or photos\") aren't supported. Use **dsvision-mcp** below for that.\n\n---\n\n## dsvision-mcp — Vision (MCP server)\n\nSame functionality as the skill above, but runs as an MCP server — bypassing two Cowork sandbox limitations:\n\n1. **Network egress** — the skill's DashScope API calls are firewalled inside Cowork's VM; the MCP server runs outside it\n2. **Inline images** — auto-picks the latest cached image from `~/.claude/image-cache/`, so drag-drop/paste/\"+\" workflows work (macOS only; Windows Cowork doesn't cache inline images to disk)\n\n### Setup\n\n```bash\npip3 install fastmcp requests\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx # add to ~/.zshrc\ncd /path/to/dsclaude && pwd # note the absolute path\n```\n\nAdd to the MCP config file matching your mode:\n\n| Mode | Config file |\n|------|-------------|\n| 3P/Gateway (DeepSeek via `dsclaude-desktop`) | `~/Library/Application Support/Claude-3p/claude_desktop_config.json` |\n| Standard Anthropic | `~/Library/Application Support/Claude/claude_desktop_config.json` |\n\n```json\n{\n \"mcpServers\": {\n \"dsvision\": {\n \"command\": \"/absolute/path/dsclaude/dsvision-mcp\"\n }\n }\n}\n```\n\nRestart Claude Desktop. The `analyze_image` tool appears automatically.\n\n### Usage\n\n```\nanalyze_image() # auto: latest cached image\nanalyze_image(image_path=\"/abs/path/foo.png\")\nanalyze_image(focus=\"What error is shown?\")\n```\n\n### Troubleshooting\n\n| Symptom | Check |\n| --------- | ------- |\n| Tool doesn't appear | Wrong config file path / invalid JSON (validate with `python3 -m json.tool`) |\n| Tool errors | `DASHSCOPE_API_KEY` not set |\n| `ModuleNotFoundError` | Use `pip3` not `pip` |\n| Image not found | Pass absolute path, or check `~/.claude/image-cache/` exists |\n\n### Skill vs MCP: which to use\n\n| Scenario | Use |\n| ---------- | ----- |\n| Claude Code (CLI), explicit paths | `skills/deepseek-vision` (zero deps) |\n| Cowork / Desktop with inline images | `dsvision-mcp` (only option that works) |\n| Cowork with explicit paths, sandbox tweaks OK | either |\n\n## Support\n\nIf these scripts save you time, consider supporting the author:\n\n<table>\n <tr>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/wechat-pay.png\" width=\"150\" alt=\"WeChat Pay\"><br><b>WeChat Pay</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/alipay.png\" width=\"150\" alt=\"Alipay\"><br><b>Alipay</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/buymeacoffee.png\" width=\"150\" alt=\"Buy Me a Coffee\"><br><b>Buy Me a Coffee</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/awarding/award.gif\" width=\"150\" alt=\"Give a Reward\"><br><b>Give a Reward</b></td>\n </tr>\n</table>\n\n## Author\n\n**Agents365-ai** · [Bilibili](https://space.bilibili.com/441831884) · [GitHub](https://github.com/Agents365-ai)\n\n## License\n\n[CC BY-NC 4.0](LICENSE.md) — free for non-commercial use. **Commercial use requires permission.**\n"}}, "docs/index.md": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785595192.1269927, "n": 8585, "h": "3630317bb4818a02", "c": "---\ntitle: dsclaude\ndescription: Claude Code & Claude Desktop launchers for alternative backends\n---\n\n**English** · [中文](zh.html) · [GitHub](https://github.com/Agents365-ai/dsclaude)\n\nA collection of launchers and configurators that point [Claude Code](https://claude.ai/code) and Claude Desktop at third-party model backends (DeepSeek, Xiaomi MiMo, etc.).\n\n**Author:** [Agents365-ai](https://github.com/Agents365-ai) · [Bilibili](https://space.bilibili.com/441831884)\n\n---\n\n## Tools\n\n| Tool | What it does | Platform | Backend |\n|------|-------------|----------|---------|\n| **[dsclaude](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude)** | Claude Code CLI launcher | macOS / Linux | DeepSeek |\n| **[mmclaude](https://github.com/Agents365-ai/dsclaude/blob/main/mmclaude)** | Claude Code CLI launcher | macOS / Linux | Xiaomi MiMo |\n| **[dsclaude-desktop](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude-desktop)** | Claude Desktop GUI configurator | macOS | DeepSeek |\n| **[dsclaude-desktop.ps1](https://github.com/Agents365-ai/dsclaude/blob/main/dsclaude-desktop.ps1)** | Claude Desktop GUI configurator | Windows | DeepSeek |\n| **[skills/deepseek-vision](https://github.com/Agents365-ai/dsclaude/tree/main/skills/deepseek-vision)** | Vision skill (zero deps) | macOS / Linux | DashScope Qwen |\n| **[dsvision-mcp](https://github.com/Agents365-ai/dsclaude/blob/main/dsvision-mcp)** | Vision MCP server | macOS / Linux | DashScope Qwen |\n\n---\n\n## Quick start on macOS\n\n```bash\ngit clone https://github.com/Agents365-ai/dsclaude.git\ncd dsclaude\nchmod +x dsclaude\n./dsclaude\n```\n\n---\n\n## dsclaude — Claude Code on DeepSeek\n\nFollows the [DeepSeek Anthropic API](https://api-docs.deepseek.com/guides/anthropic_api) guide.\n\n```bash\nexport DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxx # add to ~/.zshrc\n\ndsclaude # default: deepseek-v4-pro (full reasoning)\ndsclaude fast # deepseek-v4-flash (cheaper / faster)\ndsclaude long # request 1M context window\ndsclaude long fast # 1M + flash\n```\n\nSets the DeepSeek-recommended env vars (`ANTHROPIC_BASE_URL`, model mappings, `CLAUDE_CODE_EFFORT_LEVEL=max`), and exposes the alternate model in Claude Code's `/model` picker. Override context window via `DSCLAUDE_MAX_TOKENS` and effort via `DSCLAUDE_EFFORT`.\n\n> Both models natively support 1M-token context. The `[1m]` suffix (e.g. `deepseek-v4-pro[1m]`) is required in Claude Code — `dsclaude` sets it automatically.\n\n---\n\n## mmclaude — Claude Code on Xiaomi MiMo\n\n```bash\nexport MIMO_API_KEY=sk-xxxxxxxxxxxxxxxxxx # pay-as-you-go\n# or\nexport MIMO_API_KEY=tp-xxxxxxxxxxxxxxxxxx # Token Plan\n\nmmclaude # start on mimo-v2.5-pro\nmmclaude update # git pull\n```\n\nAuto-detects base URL from the key prefix (`sk-*` → public, `tp-*` → Token Plan); override with `MIMO_BASE_URL`. Sets all four model slots to `mimo-v2.5-pro` and unsets `ANTHROPIC_API_KEY` (per MiMo docs).\n\n---\n\n## dsclaude-desktop — Claude Desktop GUI configurator\n\nOne-command configurator for Claude Desktop's built-in **Third-Party Inference** feature (Developer menu), pre-filled for DeepSeek.\n\n### Prerequisites\n\n1. Claude Desktop installed ([claude.ai/download](https://claude.ai/download))\n2. Developer Mode enabled (Help → Troubleshooting → Enable Developer Mode, once)\n3. `DEEPSEEK_API_KEY` environment variable set\n\n### Usage (macOS)\n\n```bash\nexport DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./dsclaude-desktop # configure and restart\n./dsclaude-desktop -h # help\n```\n\nGenerates an entry under `~/Library/Application Support/Claude-3p/configLibrary/`, sets it as `appliedId` in `_meta.json`, then restarts the app. Existing GUI-added entries are preserved.\n\n### Switching modes\n\nClaude Desktop's launch chooser handles Anthropic ↔ Gateway switching natively — no `--revert` flag. Click your profile → **Disconnect** (or sign out), then pick the other option at next launch.\n\n> Classic **Chat** (claude.ai-style) is unavailable in Gateway mode — it depends on Anthropic-hosted features not exposed via the inference API. Switch back to Anthropic mode to use it.\n\n### Usage (Windows)\n\n```powershell\n$env:DEEPSEEK_API_KEY = \"sk-xxxxxxxxxxxxxxxxxx\"\npwsh ./dsclaude-desktop.ps1\n```\n\nUnlike macOS, Developer Mode is **auto-enabled** by the script — no manual GUI toggle needed.\n\nConfig path: `%LOCALAPPDATA%\\Claude-3p\\configLibrary\\` (for Store/MSIX installs, the script also writes to the sandboxed package path as a fallback).\n\nTested on Windows 11 with Claude Desktop 1.7196 (Windows Store, arm64).\n\n---\n\n## deepseek-vision skill — Vision (zero-dependency)\n\nGives text-only agents (like DeepSeek) the ability to \"see\" images. When the agent encounters an image, it calls `analyze-image`, which sends it to Qwen3.6-Flash and returns a text description.\n\n```bash\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./skills/deepseek-vision/analyze-image /path/to/screenshot.png \"What error is shown?\"\n./skills/deepseek-vision/analyze-image https://example.com/diagram.png\n```\n\nWorks with any agent that loads `SKILL.md` (Claude Code, Cowork, etc.). Default model `qwen3.6-flash`; override via `DSVISION_MODEL` and `DSVISION_BASE_URL`.\n\n> **Limitation**: requires a file path or URL — inline images (drag-drop, paste, \"+ → Add files or photos\") aren't supported. Use **dsvision-mcp** below for that.\n\n---\n\n## dsvision-mcp — Vision (MCP server)\n\nSame functionality as the skill above, but runs as an MCP server — bypassing two Cowork sandbox limitations:\n\n1. **Network egress** — the skill's DashScope API calls are firewalled inside Cowork's VM; the MCP server runs outside it\n2. **Inline images** — auto-picks the latest cached image from `~/.claude/image-cache/`, so drag-drop/paste/\"+\" workflows work (macOS only; Windows Cowork doesn't cache inline images to disk)\n\n### Setup\n\n```bash\npip3 install fastmcp requests\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx # add to ~/.zshrc\ncd /path/to/dsclaude && pwd # note the absolute path\n```\n\nAdd to the MCP config file matching your mode:\n\n| Mode | Config file |\n|------|-------------|\n| 3P/Gateway (DeepSeek via `dsclaude-desktop`) | `~/Library/Application Support/Claude-3p/claude_desktop_config.json` |\n| Standard Anthropic | `~/Library/Application Support/Claude/claude_desktop_config.json` |\n\n```json\n{\n \"mcpServers\": {\n \"dsvision\": {\n \"command\": \"/absolute/path/dsclaude/dsvision-mcp\"\n }\n }\n}\n```\n\nRestart Claude Desktop. The `analyze_image` tool appears automatically.\n\n### Usage\n\n```\nanalyze_image() # auto: latest cached image\nanalyze_image(image_path=\"/abs/path/foo.png\")\nanalyze_image(focus=\"What error is shown?\")\n```\n\n### Troubleshooting\n\n| Symptom | Check |\n|---------|-------|\n| Tool doesn't appear | Wrong config file path / invalid JSON (validate with `python3 -m json.tool`) |\n| Tool errors | `DASHSCOPE_API_KEY` not set |\n| `ModuleNotFoundError` | Use `pip3` not `pip` |\n| Image not found | Pass absolute path, or check `~/.claude/image-cache/` exists |\n\n### Skill vs MCP: which to use\n\n| Scenario | Use |\n|----------|-----|\n| Claude Code (CLI), explicit paths | `skills/deepseek-vision` (zero deps) |\n| Cowork / Desktop with inline images | `dsvision-mcp` (only option that works) |\n| Cowork with explicit paths, sandbox tweaks OK | either |\n\n---\n\n## Community\n\n- **Discord:** <https://discord.gg/79JF5Atuk>\n- **WeChat:** scan the QR code below\n\n<p align=\"center\">\n <img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/agents365ai_wechat_1.png\" width=\"200\" alt=\"WeChat Community Group\">\n</p>\n\n## Support\n\nIf these scripts save you time, consider supporting the author:\n\n<table>\n <tr>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/wechat-pay.png\" width=\"150\" alt=\"WeChat Pay\"><br><b>WeChat Pay</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/alipay.png\" width=\"150\" alt=\"Alipay\"><br><b>Alipay</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/buymeacoffee.png\" width=\"150\" alt=\"Buy Me a Coffee\"><br><b>Buy Me a Coffee</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/awarding/award.gif\" width=\"150\" alt=\"Give a Reward\"><br><b>Give a Reward</b></td>\n </tr>\n</table>\n\n## License\n\n[CC BY-NC 4.0](https://github.com/Agents365-ai/dsclaude/blob/main/LICENSE.md) — free for non-commercial use. **Commercial use requires permission.**\n"}}, "README_CN.md": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785595193.9504657, "n": 27072, "h": "a2f5a878f9afe2ad", "c": "# dsclaude — 面向非 Anthropic 后端的启动器工具集\n\n[English](README.md)\n\n让 [Claude Code](https://claude.ai/code) 和 Claude Desktop 接入 DeepSeek、小米 MiMo、阿里云百炼 Qwen、智谱 GLM、月之暗面 Kimi、火山方舟 Ark、美团 LongCat、MiniMax、腾讯 TokenHub、硅基流动 SiliconFlow 等第三方模型后端的小工具集。\n\n---\n\n## 工具一览\n\n| 脚本 | Agent | 平台 | 后端 | 模型 |\n| ------ | ------- | ------ | ------ | ------ |\n| **[dsclaude](dsclaude)** | Claude Code (CLI) | macOS / Linux | DeepSeek API(Anthropic 兼容端点) | `deepseek-v4-pro[1m]`(默认,统一推理)· `deepseek-v4-flash[1m]`(快速 / haiku 档位) |\n| **[dsclaude.ps1](dsclaude.ps1)** | Claude Code (CLI) | Windows(PowerShell 7+) | DeepSeek API(Anthropic 兼容端点) | 同上 |\n| **[mmclaude](mmclaude)** | Claude Code (CLI) | macOS / Linux | 小米 MiMo(Anthropic 兼容端点) | `mimo-v2.5-pro`(默认)· `mimo-v2.5`(快速 / haiku 档位) |\n| **[mmclaude.ps1](mmclaude.ps1)** | Claude Code (CLI) | Windows(PowerShell 7+) | 小米 MiMo(Anthropic 兼容端点) | 同上 |\n| **[qwclaude](qwclaude)** | Claude Code (CLI) | macOS / Linux | 阿里云百炼 Qwen(Anthropic 兼容端点) | `qwen3.7-max`(默认)· `qwen3.6-flash`(快速 / haiku 档位)· `qwen3.6-plus`(Coding Plan) |\n| **[qwclaude.ps1](qwclaude.ps1)** | Claude Code (CLI) | Windows(PowerShell 7+) | 阿里云百炼 Qwen(Anthropic 兼容端点) | 同上 |\n| **[glmclaude](glmclaude)** | Claude Code (CLI) | macOS / Linux | 智谱 AI GLM(Anthropic 兼容端点) | `glm-5.2`(默认)· `glm-4.7`(快速 / haiku 档位) |\n| **[glmclaude.ps1](glmclaude.ps1)** | Claude Code (CLI) | Windows(PowerShell 7+) | 智谱 AI GLM(Anthropic 兼容端点) | 同上 |\n| **[kmclaude](kmclaude)** | Claude Code (CLI) | macOS / Linux | 月之暗面 Kimi(Anthropic 兼容端点) | `kimi-k3`(默认)· `kimi-k2.5`(快速 / haiku 档位) |\n| **[kmclaude.ps1](kmclaude.ps1)** | Claude Code (CLI) | Windows(PowerShell 7+) | 月之暗面 Kimi(Anthropic 兼容端点) | 同上 |\n| **[arkclaude](arkclaude)** | Claude Code (CLI) | macOS / Linux | 火山方舟 Ark(Anthropic 兼容端点) | `doubao-seed-2.0-code`(默认)· `doubao-seed-2.0-pro`(平衡)· `doubao-seed-2.0-lite`(快速) + Kimi/DeepSeek/GLM/MiniMax 别名 |\n| **[arkclaude.ps1](arkclaude.ps1)** | Claude Code (CLI) | Windows(PowerShell 7+) | 火山方舟 Ark(Anthropic 兼容端点) | 同上 |\n| **[lcclaude](lcclaude)** | Claude Code (CLI) | macOS / Linux | 美团 LongCat(Anthropic 兼容端点) | `LongCat-2.0`(默认,1M 上下文)· `LongCat-Flash-Chat`(快速)· `LongCat-Flash-Thinking`(深度思考) |\n| **[lcclaude.ps1](lcclaude.ps1)** | Claude Code (CLI) | Windows(PowerShell 7+) | 美团 LongCat(Anthropic 兼容端点) | 同上 |\n| **[mxclaude](mxclaude)** | Claude Code (CLI) | macOS / Linux | MiniMax(Anthropic 兼容端点) | `MiniMax-M3`(默认,1M 上下文)· `MiniMax-M2.5`(快速) |\n| **[mxclaude.ps1](mxclaude.ps1)** | Claude Code (CLI) | Windows(PowerShell 7+) | MiniMax(Anthropic 兼容端点) | 同上 |\n| **[hyclaude](hyclaude)** | Claude Code (CLI) | macOS / Linux | 腾讯 TokenHub(Anthropic 兼容端点) | `hy3-preview`(默认)+ DeepSeek/Kimi/GLM/MiniMax/Qwen 别名 |\n| **[hyclaude.ps1](hyclaude.ps1)** | Claude Code (CLI) | Windows(PowerShell 7+) | 腾讯 TokenHub(Anthropic 兼容端点) | 同上 |\n| **[sfclaude](sfclaude)** | Claude Code (CLI) | macOS / Linux | 硅基流动 SiliconFlow(Anthropic 兼容端点) | `deepseek-ai/DeepSeek-V4-PRO`(默认)+ Kimi/GLM/Qwen/Yi/R1 别名 |\n| **[sfclaude.ps1](sfclaude.ps1)** | Claude Code (CLI) | Windows(PowerShell 7+) | 硅基流动 SiliconFlow(Anthropic 兼容端点) | 同上 |\n| **[xclaude](xclaude)** | 统一自动检测启动器 | macOS / Linux | 任意(自动检测已设置的 API Key) | — |\n| **[dsclaude-desktop](dsclaude-desktop)** | Claude Desktop (GUI) | macOS | DeepSeek API(Anthropic 兼容端点) | `deepseek-v4-pro` · `deepseek-v4-flash`(均启用 1M 上下文) |\n| **[dsclaude-desktop.ps1](dsclaude-desktop.ps1)** | Claude Desktop (GUI) | Windows(Store 版 & 标准安装) | DeepSeek API(Anthropic 兼容端点) | 同上 |\n| **[mmclaude-desktop](mmclaude-desktop)** | Claude Desktop (GUI) | macOS | 小米 MiMo(Anthropic 兼容端点) | `mimo-v2.5-pro` · `mimo-v2.5` |\n| **[mmclaude-desktop.ps1](mmclaude-desktop.ps1)** | Claude Desktop (GUI) | Windows | 小米 MiMo(Anthropic 兼容端点) | 同上 |\n| **[qwclaude-desktop](qwclaude-desktop)** | Claude Desktop (GUI) | macOS | 阿里云百炼 Qwen(Anthropic 兼容端点) | `qwen3.7-max` · `qwen3.6-flash`(按量/Token)· `qwen3.6-plus`(Coding Plan) |\n| **[qwclaude-desktop.ps1](qwclaude-desktop.ps1)** | Claude Desktop (GUI) | Windows | 阿里云百炼 Qwen(Anthropic 兼容端点) | 同上 |\n| **[glmclaude-desktop](glmclaude-desktop)** | Claude Desktop (GUI) | macOS | 智谱 AI GLM(Anthropic 兼容端点) | `glm-5.2` · `glm-4.7` |\n| **[glmclaude-desktop.ps1](glmclaude-desktop.ps1)** | Claude Desktop (GUI) | Windows | 智谱 AI GLM(Anthropic 兼容端点) | 同上 |\n| **[kmclaude-desktop](kmclaude-desktop)** | Claude Desktop (GUI) | macOS | 月之暗面 Kimi(Anthropic 兼容端点) | `kimi-k3` · `kimi-k2.5` |\n| **[kmclaude-desktop.ps1](kmclaude-desktop.ps1)** | Claude Desktop (GUI) | Windows | 月之暗面 Kimi(Anthropic 兼容端点) | 同上 |\n| **[arkclaude-desktop](arkclaude-desktop)** | Claude Desktop (GUI) | macOS | 火山方舟 Ark(Anthropic 兼容端点) | `doubao-seed-2.0-code` · `doubao-seed-2.0-pro` · `doubao-seed-2.0-lite` + Kimi/DeepSeek/GLM/MiniMax |\n| **[arkclaude-desktop.ps1](arkclaude-desktop.ps1)** | Claude Desktop (GUI) | Windows | 火山方舟 Ark(Anthropic 兼容端点) | 同上 |\n| **[lcclaude-desktop](lcclaude-desktop)** | Claude Desktop (GUI) | macOS | 美团 LongCat(Anthropic 兼容端点) | `LongCat-2.0` · `LongCat-Flash-Chat` |\n| **[lcclaude-desktop.ps1](lcclaude-desktop.ps1)** | Claude Desktop (GUI) | Windows | 美团 LongCat(Anthropic 兼容端点) | 同上 |\n| **[mxclaude-desktop](mxclaude-desktop)** | Claude Desktop (GUI) | macOS | MiniMax(Anthropic 兼容端点) | `MiniMax-M3` · `MiniMax-M2.5` |\n| **[mxclaude-desktop.ps1](mxclaude-desktop.ps1)** | Claude Desktop (GUI) | Windows | MiniMax(Anthropic 兼容端点) | 同上 |\n| **[hyclaude-desktop](hyclaude-desktop)** | Claude Desktop (GUI) | macOS | 腾讯 TokenHub(Anthropic 兼容端点) | `hy3-preview` + DeepSeek/Kimi/GLM/MiniMax/Qwen |\n| **[hyclaude-desktop.ps1](hyclaude-desktop.ps1)** | Claude Desktop (GUI) | Windows | 腾讯 TokenHub(Anthropic 兼容端点) | 同上 |\n| **[sfclaude-desktop](sfclaude-desktop)** | Claude Desktop (GUI) | macOS | 硅基流动 SiliconFlow(Anthropic 兼容端点) | `deepseek-ai/DeepSeek-V4-PRO` + Kimi/GLM/Qwen/Yi/R1 |\n| **[sfclaude-desktop.ps1](sfclaude-desktop.ps1)** | Claude Desktop (GUI) | Windows | 硅基流动 SiliconFlow(Anthropic 兼容端点) | 同上 |\n| **[skills/deepseek-vision](skills/deepseek-vision/)** | skill(任何加载 SKILL.md 的 agent) | macOS / Linux | DashScope(OpenAI/Anthropic 兼容) | `qwen3.6-flash`(默认视觉模型) |\n| **[dsvision-mcp](dsvision-mcp)** | MCP server(Claude Desktop / Cowork / 任何 MCP 客户端) | macOS / Linux | DashScope | `qwen3.6-flash`(默认视觉模型) |\n\n---\n\n## 工作原理\n\n\n\n脚本逻辑总览:安装器、`xclaude` 自动检测调度器、各后端 CLI 启动器、Claude Desktop 配置器与 Codex 桥接,全部共享 `lib/common.sh`。PNG 内嵌 draw.io XML,用 [draw.io](https://app.diagrams.net) 打开即可继续编辑([中文源文件](docs/xxclaude-logic-cn.drawio) · [English version](docs/xxclaude-logic.drawio.png))。\n\n---\n\n## macOS 快速开始\n\n```bash\n# 一行安装(推荐):\ncurl -fsSL https://raw.githubusercontent.com/Agents365-ai/dsclaude/main/install.sh | bash\n\n# 或用户目录安装(无需 sudo):\ncurl -fsSL https://raw.githubusercontent.com/Agents365-ai/dsclaude/main/install.sh | bash -s -- --user\n\n# 或手动安装:\ngit clone https://github.com/Agents365-ai/dsclaude.git\ncd dsclaude\nchmod +x xclaude\n./xclaude\n```\n\n## Windows 快速开始\n\n```powershell\n# 一行安装(建议以管理员运行 PowerShell):\nirm https://raw.githubusercontent.com/Agents365-ai/dsclaude/main/install.ps1 | iex\n\n# 安装并自动添加 PATH:\nirm https://raw.githubusercontent.com/Agents365-ai/dsclaude/main/install.ps1 | iex -AddToPath\n\n# 然后启动:\npwsh -File xclaude.ps1\n```\n\n---\n\n## xclaude — 统一自动检测启动器\n\n不记得该用哪个脚本?`xclaude` 自动检测你设置的 API Key 并委托给对应的后端启动器。\n\n```bash\n# 在 ~/.zshrc 中设置任意一个即可:\nexport DEEPSEEK_API_KEY=sk-... # → dsclaude\nexport GLM_API_KEY=... # → glmclaude\nexport KIMI_API_KEY=sk-... # → kmclaude\nexport ARK_API_KEY=... # → arkclaude\n# ... 或其他支持的 Key\n\nxclaude # 自动检测并启动\nxclaude fast # 使用 fast/flash 档位\nxclaude long effort max # 1M 上下文 + max 推理等级\nxclaude kimi # 转发:在 Ark/TokenHub 上 → kimi 模型\n```\n\n所有位置参数(模型别名、`fast`、`long`、`effort` 等)均透传给底层启动器。如果同时设置了多个 Key,按检测顺序选第一个;可设置 `XCLAUDE_PREFER=dsclaude` 来强制指定。\n\n---\n\n## dsclaude — Claude Code 接入 DeepSeek\n\n遵循 [DeepSeek Anthropic API](https://api-docs.deepseek.com/guides/anthropic_api) 指南。\n\n```bash\nexport DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 添加到 ~/.zshrc\n\ndsclaude # 默认 deepseek-v4-pro(完整推理)\ndsclaude fast # deepseek-v4-flash(更快更便宜)\ndsclaude long # 1M 上下文窗口\ndsclaude long fast # 1M + flash\n```\n\n自动设置 DeepSeek 推荐的环境变量(`ANTHROPIC_BASE_URL`、模型映射、`CLAUDE_CODE_EFFORT_LEVEL=max`),并在 `/model` 选择器中暴露备选模型。上下文窗口上限可通过 `DSCLAUDE_MAX_TOKENS` 覆盖,effort 级别通过 `DSCLAUDE_EFFORT` 覆盖。\n\n> 两个模型都原生支持 1M token,在 Claude Code 中需加 `[1m]` 后缀(如 `deepseek-v4-pro[1m]`),脚本已自动处理。\n>\n> Windows(PowerShell 7+):`pwsh -File ./dsclaude.ps1`(参数相同)。\n\n---\n\n## mmclaude — Claude Code 接入小米 MiMo\n\n```bash\nexport MIMO_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 按量付费\n# 或\nexport MIMO_API_KEY=tp-xxxxxxxxxxxxxxxxxx # Token Plan\n\nmmclaude # 启动 mimo-v2.5-pro\nmmclaude fast # 启动 mimo-v2.5(更便宜 / 更快的 flash 档)\nmmclaude update # git pull 拉取更新\n```\n\n按 key 前缀自动选择 base URL(`sk-*` → 公网,`tp-*` → Token Plan),可用 `MIMO_BASE_URL` 覆盖。main/opus/sonnet 槽位使用 `mimo-v2.5-pro`,haiku 与子代理(subagent)档使用 `mimo-v2.5`(flash);`mmclaude fast` 会把主模型切到 flash,另一档会出现在 `/model` 选择器里以便会话中切换。自动 unset `ANTHROPIC_API_KEY`(避免遮蔽 bearer token)。可用 `MIMO_MODEL` / `MIMO_FLASH_MODEL` 覆盖两档模型。\n\n> Windows(PowerShell 7+):`pwsh -File ./mmclaude.ps1`(参数相同)。\n\n---\n\n## qwclaude — Claude Code 接入阿里云百炼 Qwen\n\n```bash\n# 每个套餐一把 key,分别来自百炼控制台不同入口:\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 按量付费\nexport DASHSCOPE_CP_API_KEY=sk-xxxxxxxxxxxxxxxxxx # Coding Plan\nexport DASHSCOPE_TP_API_KEY=sk-xxxxxxxxxxxxxxxxxx # Token Plan 团队版\n\n# macOS / Linux — 三个模型档位\nqwclaude # 按量付费,qwen3.7-max(北京) → DASHSCOPE_API_KEY\nqwclaude plus # qwen3.7-plus(平衡之选,约 max 的 1/6 价格)\nqwclaude max # 显示指定 qwen3.7-max\nqwclaude fast # qwen3.6-flash 作主模型\nqwclaude intl # 按量付费,新加坡端点\nqwclaude coding # Coding Plan(qwen3.7-plus 推荐) → DASHSCOPE_CP_API_KEY\nqwclaude coding plus # Coding Plan,qwen3.7-plus(默认)\nqwclaude coding fast # Coding Plan,qwen3.6-plus\nqwclaude token # Token Plan(qwen3.7-max) → DASHSCOPE_TP_API_KEY\nqwclaude token plus # Token Plan,qwen3.7-plus\nqwclaude update # git pull 拉取更新\n\n# Windows(PowerShell 7+)\npwsh -File ./qwclaude.ps1 coding\n```\n\n按所选套餐与模型档位自动选择 base URL、模型阵容与 API key 变量。三个模型档位:\n\n| 档位 | 按量付费 / Token Plan | Coding Plan |\n| ------ | ---------------------- | ------------- |\n| **max**(默认) | `qwen3.7-max`(旗舰推理) | 不可用 |\n| **plus** | `qwen3.7-plus`(平衡,约 max 的 1/6) | `qwen3.7-plus`(推荐) |\n| **flash**(subagent/haiku 档) | `qwen3.6-flash` | `qwen3.6-plus` |\n\nMain/opus/sonnet 槽位运行所选档位(默认 `qwen3.7-max`),haiku 与子代理(subagent)档始终使用 flash 模型。`fast` 把主模型切到 flash;`plus` 切到 qwen3.7-plus。另一档会出现在 `/model` 选择器里以便会话中切换。设置 `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` 并 unset `ANTHROPIC_API_KEY`,把流量锁定在百炼(避免连到 `api.anthropic.com` 报错)。可用 `QWEN_PLAN` / `QWEN_REGION` / `QWEN_MODEL` / `QWEN_PLUS_MODEL` / `QWEN_FLASH_MODEL` / `QWEN_BASE_URL` 覆盖。\n\n> Windows 版(`qwclaude.ps1`)需要 PowerShell 7+(`winget install Microsoft.PowerShell`),用 `pwsh -File` 运行。\n\n---\n\n## glmclaude — Claude Code 接入智谱 AI GLM\n\n遵循智谱 AI 的 Anthropic 兼容 API。\n\n```bash\nexport GLM_API_KEY=你的智谱API_KEY # 添加到 ~/.zshrc\n# 在 https://open.bigmodel.cn/usercenter/apikeys 获取你的 key\n\nglmclaude # 默认 glm-5.2(完整推理)\nglmclaude fast # glm-4.7(更快更便宜)\nglmclaude update # git pull 拉取更新\n```\n\n自动设置智谱推荐的环境变量(`ANTHROPIC_BASE_URL`、模型映射),并在 `/model` 选择器中暴露备选模型。main/opus/sonnet 槽位使用 `glm-5.2`,haiku 与子代理(subagent)档使用 `glm-4.7`;`glmclaude fast` 会把主模型切到 flash,另一档会出现在 `/model` 选择器里以便会话中切换。\n\n默认使用国内端点(`https://open.bigmodel.cn/api/anthropic`)。如需使用海外端点,设置 `GLM_BASE_URL`:\n\n```bash\nexport GLM_BASE_URL=https://api.z.ai/api/anthropic\nglmclaude\n```\n\n可用 `GLM_MODEL` / `GLM_FLASH_MODEL` 覆盖两档模型。\n\n> Windows(PowerShell 7+):`pwsh -File ./glmclaude.ps1`(参数相同)。\n\n---\n\n## kmclaude — Claude Code 接入月之暗面 Kimi\n\n遵循月之暗面 Kimi 的 Anthropic 兼容 API。\n\n```bash\nexport KIMI_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 添加到 ~/.zshrc\n# 在 https://platform.moonshot.cn/console/api-keys 获取你的 key\n\nkmclaude # 默认 kimi-k3(旗舰推理)\nkmclaude fast # kimi-k2.5(更快更便宜)\nkmclaude update # git pull 拉取更新\n```\n\n使用 Kimi 官方 Anthropic 兼容端点(`https://api.moonshot.cn/anthropic`)。main/opus/sonnet 槽位使用 `kimi-k3`,haiku 与子代理(subagent)档使用 `kimi-k2.5`;`kmclaude fast` 会把主模型切到 flash,另一档会出现在 `/model` 选择器里以便会话中切换。自动 unset `ANTHROPIC_API_KEY`(避免遮蔽 bearer token)。可用 `KIMI_MODEL` / `KIMI_FLASH_MODEL` 覆盖两档模型,`KIMI_BASE_URL` 覆盖端点地址。\n\n> Windows(PowerShell 7+):`pwsh -File ./kmclaude.ps1`(参数相同)。\n\n---\n\n## dsclaude-desktop — Claude Desktop GUI 配置器\n\n一键配置 Claude Desktop **内置**的 Third-Party Inference 功能(Developer 菜单),预填 DeepSeek 参数并重启 App。\n\n### 前置条件\n\n1. 已安装 Claude Desktop([claude.ai/download](https://claude.ai/download))\n2. 已启用 Developer Mode(Help → Troubleshooting → Enable Developer Mode,一次即可)\n3. 已设置 `DEEPSEEK_API_KEY` 环境变量\n\n### 用法\n\n```bash\nexport DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./dsclaude-desktop # 配置并重启\n./dsclaude-desktop -h # 帮助\n```\n\n脚本在 `~/Library/Application Support/Claude-3p/configLibrary/` 下生成配置 entry,将其设为 `appliedId`,然后重启 App。原本通过 GUI 添加的其他 entry 不受影响。\n\n### 模式切换\n\nClaude Desktop 启动选择器原生支持 Anthropic ↔ Gateway 切换,无需 `--revert`。在 App 内点头像 → Disconnect,下次启动时选另一个入口即可。\n\n> 唯一不可用的功能是经典 **Chat**(依赖 Anthropic 托管服务且不在 inference API 表面)。需要用 Chat 时切回 Anthropic 模式即可。\n\n### Windows 版本\n\n```powershell\n$env:DEEPSEEK_API_KEY = \"sk-xxxxxxxxxxxxxxxxxx\"\npwsh ./dsclaude-desktop.ps1\n```\n\n配置目录为 `%APPDATA%\\Claude-3p\\configLibrary\\`。> 作者未在 Windows 上实测,如有问题请[提 issue](https://github.com/Agents365-ai/dsclaude/issues)。\n\n---\n前置条件:Claude Desktop 已安装(Store 版或标准安装均可)、有 DeepSeek API Key。**无需手动启用 Developer Mode**——脚本会自动创建 `developer_settings.json`。\n\n配置目录:`%LOCALAPPDATA%\\Claude-3p\\configLibrary\\`(若为 Store/MSIX 安装,脚本还会额外写入沙箱路径 `LocalCache\\Roaming\\Claude-3p\\configLibrary\\` 作为后备)。\n\n已在 Windows 11 + Claude Desktop 1.7196(Windows Store, arm64)上实测通过。\n\n---\n\n## mmclaude-desktop — Claude Desktop 接入小米 MiMo\n\n与 `dsclaude-desktop` 相同的配置器,预填小米 MiMo。读取 `MIMO_API_KEY`,按 key 前缀自动选择 base URL(`tp-*` → Token Plan,否则按量付费;可用 `MIMO_BASE_URL` 覆盖),配置 `mimo-v2.5-pro` + `mimo-v2.5`。\n\n```bash\nexport MIMO_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 或 tp-... 表示 Token Plan\n./mmclaude-desktop # 配置并重启(macOS)\n./mmclaude-desktop -h # 帮助\n\n# Windows(PowerShell)\n$env:MIMO_API_KEY = \"sk-xxxxxxxxxxxxxxxxxx\"\npwsh ./mmclaude-desktop.ps1\n```\n\n---\n\n## qwclaude-desktop — Claude Desktop 接入阿里云百炼 Qwen\n\n同款配置器,按套餐与模型档位自动选择 base URL、模型与 key 变量。按量付费(`DASHSCOPE_API_KEY`)与 Token Plan(`DASHSCOPE_TP_API_KEY`)配置 `qwen3.7-max` + `qwen3.6-flash`;Coding Plan(`DASHSCOPE_CP_API_KEY`)配置 `qwen3.7-plus` + `qwen3.6-plus`。添加 `plus` 参数可在任意套餐中使用 qwen3.7-plus。\n\n```bash\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 按量付费\nexport DASHSCOPE_CP_API_KEY=sk-xxxxxxxxxxxxxxxxxx # Coding Plan\nexport DASHSCOPE_TP_API_KEY=sk-xxxxxxxxxxxxxxxxxx # Token Plan\n\n./qwclaude-desktop # 按量付费(北京),qwen3.7-max,然后重启\n./qwclaude-desktop plus # 按量付费,qwen3.7-plus\n./qwclaude-desktop intl # 按量付费,新加坡端点\n./qwclaude-desktop coding # Coding Plan(qwen3.7-plus)\n./qwclaude-desktop token # Token Plan,qwen3.7-max\n./qwclaude-desktop token plus # Token Plan,qwen3.7-plus\n\n# Windows(PowerShell)\npwsh ./qwclaude-desktop.ps1 -Plan coding\npwsh ./qwclaude-desktop.ps1 -Plan token -ModelTier plus\n```\n\n> 两个 `.ps1` Windows 版移植自 `dsclaude-desktop.ps1`,**作者未在 Windows 上实测**,如有问题请[提 issue](https://github.com/Agents365-ai/dsclaude/issues)。两个配置器都会设置 `unstableDisableModelVerification`,让 Claude Desktop 接受非 Anthropic 的模型名;与 `dsclaude-desktop` 一样,网关启用期间 Chat 模式不可用。\n\n## glmclaude-desktop — Claude Desktop 接入智谱 AI GLM\n\n同款配置器,预填智谱 GLM。读取 `GLM_API_KEY`,配置 `glm-5.2` + `glm-4.7`。\n\n```bash\nexport GLM_API_KEY=你的智谱API_KEY\n./glmclaude-desktop # 配置并重启(macOS)\n./glmclaude-desktop -h # 帮助\n\n# Windows(PowerShell)\n$env:GLM_API_KEY = \"你的智谱API_KEY\"\npwsh ./glmclaude-desktop.ps1\n```\n\n可通过 `GLM_BASE_URL` 覆盖 base URL(默认:`https://open.bigmodel.cn/api/anthropic`)。\n\n---\n\n## kmclaude-desktop — Claude Desktop 接入月之暗面 Kimi\n\n同款配置器,预填 Kimi。读取 `KIMI_API_KEY`,配置 `kimi-k3` + `kimi-k2.5`。\n\n```bash\nexport KIMI_API_KEY=你的Kimi_API_KEY\n./kmclaude-desktop # 配置并重启(macOS)\n./kmclaude-desktop -h # 帮助\n\n# Windows(PowerShell)\n$env:KIMI_API_KEY = \"你的Kimi_API_KEY\"\npwsh ./kmclaude-desktop.ps1\n```\n\n可通过 `KIMI_BASE_URL` 覆盖 base URL(默认:`https://api.moonshot.cn/anthropic`)。\n\n---\n\n## arkclaude — Claude Code 接入火山方舟 Ark(Coding Plan)\n\n火山方舟 Ark Coding Plan 是一个多模型聚合平台 — 一次订阅即可使用豆包、Kimi、DeepSeek、GLM、MiniMax 等多家模型。一个 API Key、一个端点、多模型随意切换。\n\n```bash\nexport ARK_API_KEY=你的Ark_API_KEY # 添加到 ~/.zshrc\n# 在 https://console.volcengine.com/ark 获取你的 key\n\n# 三种豆包档位 + 厂商别名快速切换\narkclaude # doubao-seed-2.0-code(代码专项,默认)\narkclaude plus # doubao-seed-2.0-pro(平衡之选)\narkclaude fast # doubao-seed-2.0-lite(轻量快速)\narkclaude kimi # kimi-k2.7-code(Kimi 代码模型)\narkclaude kimi-pro # kimi-k2.6\narkclaude deepseek # deepseek-v4-pro\narkclaude deepseek-flash # deepseek-v4-flash\narkclaude glm # glm-5.2\narkclaude minimax # minimax-m2.7\narkclaude update # git pull 拉取更新\n```\n\n使用 Ark Coding Plan 端点(`https://ark.cn-beijing.volces.com/api/coding`)。main/opus/sonnet 槽位运行所选模型,haiku 与子代理(subagent)档始终使用同一家族中最便宜的模型(或 `doubao-seed-2.0-lite` 作为降级)。`/model` 选择器会根据当前选择智能暴露对应备选 — 用 doubao 时暴露 Pro↔Code,用 Kimi 时暴露 K2.6↔K2.7-code 等。设置 `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1` 并 unset `ANTHROPIC_API_KEY`。可用 `ARK_MODEL` / `ARK_PLUS_MODEL` / `ARK_FLASH_MODEL` / `ARK_BASE_URL` 覆盖。\n\n> Windows(PowerShell 7+):`pwsh -File ./arkclaude.ps1`(参数相同)。\n\n---\n\n## arkclaude-desktop — Claude Desktop 接入火山方舟 Ark\n\n同款配置器,预填 Ark Coding Plan。读取 `ARK_API_KEY`。支持所有模型别名。\n\n```bash\nexport ARK_API_KEY=你的Ark_API_KEY\n./arkclaude-desktop # 配置 doubao-seed-2.0-code 并重启\n./arkclaude-desktop plus # doubao-seed-2.0-pro\n./arkclaude-desktop kimi # kimi-k2.7-code\n./arkclaude-desktop deepseek # deepseek-v4-pro\n./arkclaude-desktop glm # glm-5.2\n./arkclaude-desktop minimax # minimax-m2.7\n./arkclaude-desktop -h # 帮助\n\n# Windows(PowerShell)\n$env:ARK_API_KEY = \"你的Ark_API_KEY\"\npwsh ./arkclaude-desktop.ps1 -ModelTier kimi\n```\n\n可通过 `ARK_BASE_URL` 覆盖 base URL(默认:`https://ark.cn-beijing.volces.com/api/coding`)。\n\n---\n\n## lcclaude — Claude Code 接入美团 LongCat\n\nLongCat-2.0 是美团自研的 1.6 万亿参数 MoE 大模型,全程国产算力训练,1M 原生上下文窗口。OpenRouter 数据显示 LongCat-2.0 在 Claude Code 月调用量位列全球第二。**公测期间免费** — 每日 50 万 Token。\n\n```bash\nexport LONGCAT_API_KEY=lc-xxxxxxxxxxxxxxxxxx # 添加到 ~/.zshrc\n# 在 https://longcat.chat/platform 免费获取 key\n\nlcclaude # LongCat-2.0(1M 上下文,旗舰模型)\nlcclaude fast # LongCat-Flash-Chat(快速/便宜)\nlcclaude think # LongCat-Flash-Thinking(深度推理)\nlcclaude update # git pull 拉取更新\n```\n\n使用 LongCat 官方 Anthropic 兼容端点(`https://api.longcat.chat/anthropic`)。main/opus/sonnet 槽位运行所选模型,haiku 与子代理(subagent)档使用 `LongCat-Flash-Chat`。`/model` 选择器暴露备选档位。可用 `LONGCAT_MODEL` / `LONGCAT_FLASH_MODEL` / `LONGCAT_THINK_MODEL` / `LONGCAT_BASE_URL` 覆盖。\n\n> Windows(PowerShell 7+):`pwsh -File ./lcclaude.ps1`(参数相同)。\n\n---\n\n## lcclaude-desktop — Claude Desktop 接入美团 LongCat\n\n同款配置器,预填 LongCat。读取 `LONGCAT_API_KEY`,配置 `LongCat-2.0` + `LongCat-Flash-Chat`。\n\n```bash\nexport LONGCAT_API_KEY=lc-xxxxxxxxxxxxxxxxxx\n./lcclaude-desktop # 配置并重启(macOS)\n./lcclaude-desktop -h # 帮助\n\n# Windows(PowerShell)\n$env:LONGCAT_API_KEY = \"lc-xxxxxxxxxxxxxxxxxx\"\npwsh ./lcclaude-desktop.ps1\n```\n\n可通过 `LONGCAT_BASE_URL` 覆盖 base URL(默认:`https://api.longcat.chat/anthropic`)。\n\n---\n\n## mxclaude — Claude Code 接入 MiniMax\n\nMiniMax-M3 是 1M 上下文旗舰模型,专为 Agent 推理、工具调用和编程场景优化。**需要使用 Coding Plan(Token Plan)API Key**,按量付费 key 不可用。\n\n```bash\nexport MINIMAX_API_KEY=你的MiniMax_API_KEY # 添加到 ~/.zshrc\n# 在 https://platform.minimaxi.com 获取你的 key\n\nmxclaude # MiniMax-M3(1M 上下文,旗舰模型)\nmxclaude fast # MiniMax-M2.5(快速/便宜)\nmxclaude long # 1M 上下文窗口\nmxclaude effort max # 设置推理等级(low|medium|high|xhigh|max)\nmxclaude update # git pull 拉取更新\n```\n\n使用 MiniMax 官方 Anthropic 兼容端点(默认国内:`https://api.minimaxi.com/anthropic`;国际站:`https://api.minimax.io/anthropic`,通过 `MINIMAX_BASE_URL` 设置)。main/opus/sonnet 槽位运行所选模型,haiku 与子代理(subagent)档使用 `MiniMax-M2.5`。`/model` 选择器暴露备选档位。可用 `MINIMAX_MODEL` / `MINIMAX_FLASH_MODEL` / `MINIMAX_BASE_URL` / `MINIMAX_CTX` / `MINIMAX_OUTPUT` / `MINIMAX_EFFORT` 覆盖。\n\n> Windows(PowerShell 7+):`pwsh -File ./mxclaude.ps1`(参数相同)。\n\n---\n\n## mxclaude-desktop — Claude Desktop 接入 MiniMax\n\n同款配置器,预填 MiniMax。读取 `MINIMAX_API_KEY`,配置 `MiniMax-M3` + `MiniMax-M2.5`。\n\n```bash\nexport MINIMAX_API_KEY=你的MiniMax_API_KEY\n./mxclaude-desktop # 配置并重启(macOS)\n./mxclaude-desktop -h # 帮助\n\n# Windows(PowerShell)\n$env:MINIMAX_API_KEY = \"你的MiniMax_API_KEY\"\npwsh ./mxclaude-desktop.ps1\n```\n\n可通过 `MINIMAX_BASE_URL` 覆盖 base URL默认国内:`https://api.minimaxi.com/anthropic`;国际站:`https://api.minimax.io/anthropic`)。\n\n---\n\n## hyclaude — Claude Code 接入腾讯 TokenHub\n\n腾讯 TokenHub 是多模型聚合平台 — 一次订阅即可使用混元(HY3)、DeepSeek、GLM、Kimi、MiniMax、Qwen 等多家模型。\n\n```bash\nexport HY_API_KEY=你的API_KEY # 添加到 ~/.zshrc\n# 在 https://cloud.tencent.com/product/lkeap 获取你的 key\n\nhyclaude # hy3-preview(腾讯默认)\nhyclaude fast # hy-mt2-lite(轻量快速)\nhyclaude deepseek # deepseek-v4-pro\nhyclaude kimi # kimi-k2.7-code\nhyclaude glm # glm-5.2\nhyclaude minimax # minimax-m3\nhyclaude qwen # qwen3.5-plus\nhyclaude long # 最大上下文窗口\nhyclaude effort max # 设置推理等级(low|medium|high|xhigh|max)\nhyclaude update # git pull 拉取更新\n```\n\n使用 TokenHub Anthropic 兼容端点(默认:`https://api.lkeap.cloud.tencent.com/plan/anthropic`)。main/opus/sonnet 槽位运行所选模型,haiku 与子代理(subagent)档使用 `hy-mt2-lite`(或同家族 flash 模型)。`/model` 选择器智能暴露对应备选。可用 `HY_MODEL` / `HY_FLASH_MODEL` / `HY_BASE_URL` / `HY_CTX` / `HY_OUTPUT` / `HY_EFFORT` 覆盖。\n\n> Windows(PowerShell 7+):`pwsh -File ./hyclaude.ps1`(参数相同)。\n\n---\n\n## hyclaude-desktop — Claude Desktop 接入腾讯 TokenHub\n\n同款配置器,预填 TokenHub。读取 `HY_API_KEY`。支持模型别名选定后端模型。\n\n```bash\nexport HY_API_KEY=你的API_KEY\n./hyclaude-desktop # 配置 hy3-preview 并重启\n./hyclaude-desktop kimi # kimi-k2.7-code\n./hyclaude-desktop deepseek # deepseek-v4-pro\n./hyclaude-desktop glm # glm-5.2\n./hyclaude-desktop minimax # minimax-m3\n./hyclaude-desktop qwen # qwen3.5-plus\n./hyclaude-desktop -h # 帮助\n\n# Windows(PowerShell)\n$env:HY_API_KEY = \"你的API_KEY\"\npwsh ./hyclaude-desktop.ps1 -ModelTier kimi\n```\n\n可通过 `HY_BASE_URL` 覆盖 base URL(默认:`https://api.lkeap.cloud.tencent.com/plan/anthropic`)。\n\n---\n\n## sfclaude — Claude Code 接入硅基流动 SiliconFlow\n\n硅基流动是多模型平台,聚合了 DeepSeek、Kimi、GLM、MiniMax、Qwen、Yi 等模型。模型名称使用 `provider/Model-Name` 格式(如 `deepseek-ai/DeepSeek-V4-PRO`)。\n\n```bash\nexport SF_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 添加到 ~/.zshrc\n# 在 https://cloud.siliconflow.cn/account/ak 获取 key\n\nsfclaude # deepseek-ai/DeepSeek-V4-PRO(默认)\nsfclaude fast # deepseek-ai/DeepSeek-V3(轻量快速)\nsfclaude kimi # moonshotai/Kimi-K2-Instruct-0905\nsfclaude glm # Pro/zai-org/GLM-5\nsfclaude minimax # Pro/MiniMaxAI/MiniMax-M2.5\nsfclaude qwen # Qwen/Qwen2.5-Coder\nsfclaude yi # 01-ai/Yi-1.5\nsfclaude r1 # deepseek-ai/DeepSeek-R1(深度推理)\nsfclaude long # 最大上下文窗口\nsfclaude effort max # 设置推理等级(low|medium|high|xhigh|max)\nsfclaude update # git pull 拉取更新\n```\n\n使用硅基流动 Anthropic 兼容端点(`https://api.siliconflow.cn/`)。main/opus/sonnet 槽位运行所选模型,haiku 与子代理(subagent)档使用 `deepseek-ai/DeepSeek-V3`。可用 `SF_MODEL` / `SF_FLASH_MODEL` / `SF_BASE_URL` / `SF_CTX` / `SF_OUTPUT` / `SF_EFFORT` 覆盖。\n\n> Windows(PowerShell 7+):`pwsh -File ./sfclaude.ps1`(参数相同)。\n\n---\n\n## sfclaude-desktop — Claude Desktop 接入 SiliconFlow\n\n同款配置器,预填硅基流动。读取 `SF_API_KEY`。支持模型别名。\n\n```bash\nexport SF_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./sfclaude-desktop # deepseek-ai/DeepSeek-V4-PRO 并重启\n./sfclaude-desktop kimi # moonshotai/Kimi-K2-Instruct-0905\n./sfclaude-desktop r1 # deepseek-ai/DeepSeek-R1\n./sfclaude-desktop -h # 帮助\n\n# Windows(PowerShell)\n$env:SF_API_KEY = \"sk-xxxxxxxxxxxxxxxxxx\"\npwsh ./sfclaude-desktop.ps1 -ModelTier kimi\n```\n\n---\n\n## deepseek-vision skill — 视觉识别(零依赖方案)\n\n---\n\n## deepseek-vision skill — 视觉识别(零依赖方案)\n\n给纯文本模型(如 DeepSeek)补上\"看图\"能力的 skill。代理遇到图片时调 `analyze-image` 脚本,发给 Qwen3.6-Flash 识别后将描述返回主模型。\n\n```bash\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx\n./skills/deepseek-vision/analyze-image /path/to/screenshot.png \"图里报的什么错?\"\n./skills/deepseek-vision/analyze-image https://example.com/diagram.png\n```\n\n任何加载 `SKILL.md` 的 agent(Claude Code、Cowork 等)都能用它。默认模型 `qwen3.6-flash`,可通过 `DSVISION_MODEL` 和 `DSVISION_BASE_URL` 切换。\n\n> **限制**:需文件路径或 URL,不支持拖拽/粘贴/「+ → Add files or photos」上传的图片。这类场景请用下方的 **dsvision-mcp**。\n\n---\n\n## dsvision-mcp — 视觉识别(MCP 方案)\n\n功能同上,但以 MCP 服务形式运行,绕过 Cowork 沙箱的两个限制:\n\n1. **网络出口管制** — skill 调 DashScope API 会被沙箱防火墙拦截,MCP 服务跑在沙箱外\n2. **内联图片** — 自动读取 `~/.claude/image-cache/` 中最新缓存,拖拽/粘贴/菜单上传均可正常工作(仅 macOS,Windows Cowork 不缓存内联图)\n\n### 安装\n\n```bash\npip3 install fastmcp requests\nexport DASHSCOPE_API_KEY=sk-xxxxxxxxxxxxxxxxxx # 建议加到 ~/.zshrc\ncd /path/to/dsclaude && pwd # 记下绝对路径\n```\n\n然后根据当前模式,在对应的配置文件中添加 MCP 服务:\n\n| 模式 | 配置文件 |\n|------|----------|\n| 3P/Gateway(通过 `dsclaude-desktop` 使用 DeepSeek) | `~/Library/Application Support/Claude-3p/claude_desktop_config.json` |\n| 标准 Anthropic 模式 | `~/Library/Application Support/Claude/claude_desktop_config.json` |\n\n```json\n{\n \"mcpServers\": {\n \"dsvision\": {\n \"command\": \"/绝对/路径/dsclaude/dsvision-mcp\"\n }\n }\n}\n```\n\n重启 Claude Desktop 后,`analyze_image` 工具自动出现。\n\n### 用法\n\n```\nanalyze_image() # 自动检测最新缓存图片\nanalyze_image(image_path=\"/绝对/路径/foo.png\")\nanalyze_image(focus=\"图里报的什么错?\") # 自定义 prompt\n```\n\n### 常见问题\n\n| 现象 | 排查方向 |\n| ------ | ---------- |\n| 工具不显示 | 配置文件路径选错 / JSON 格式错误(用 `python3 -m json.tool` 校验) |\n| 工具报错 | `DASHSCOPE_API_KEY` 未设置 |\n| `ModuleNotFoundError` | 用 `pip3` 而非 `pip` |\n| 找不到图片 | 传绝对路径,或检查 `~/.claude/image-cache/` 是否存在 |\n\n### skill vs MCP 怎么选\n\n| 场景 | 推荐 |\n| ------ | ------ |\n| Claude Code (CLI),给明确路径 | `skills/deepseek-vision`(零依赖) |\n| Cowork / Desktop,拖拽/粘贴内联图 | `dsvision-mcp`(唯一能用的) |\n| Cowork,给明确路径,不介意沙箱限制 | 两者均可 |\n\n---\n\n## 赞赏支持\n\n如果这些脚本为你节省了时间,欢迎支持作者:\n\n<table>\n <tr>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/wechat-pay.png\" width=\"150\" alt=\"微信支付\"><br><b>微信支付</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/alipay.png\" width=\"150\" alt=\"支付宝\"><br><b>支付宝</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/qrcode/buymeacoffee.png\" width=\"150\" alt=\"Buy Me a Coffee\"><br><b>Buy Me a Coffee</b></td>\n <td align=\"center\"><img src=\"https://raw.githubusercontent.com/Agents365-ai/images_payment/main/awarding/award.gif\" width=\"150\" alt=\"打赏\"><br><b>打赏鼓励</b></td>\n </tr>\n</table>\n\n## 作者\n\n**Agents365-ai** · [Bilibili](https://space.bilibili.com/441831884) · [GitHub](https://github.com/Agents365-ai)\n\n## 开源协议\n\n[CC BY-NC 4.0](LICENSE.md) — 非商业用途免费。**商业使用需获得授权。**\n"}}, "lcclaude": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785674294.648063, "n": 4503, "h": "ce982304950b46b9", "c": "#!/usr/bin/env bash\n# shellcheck disable=SC2034 # variables consumed by lib/common.sh\n# lcclaude — launch Claude Code on Meituan LongCat's Anthropic-compatible API.\n#\n# Uses the official LongCat Anthropic-compatible endpoint:\n# https://api.longcat.chat/anthropic\n#\n# LongCat-2.0 is a 1.6T-param MoE model with native 1M context, built entirely\n# on Chinese-manufactured compute. It ranked #2 globally in Claude Code monthly\n# call volume on OpenRouter (behind only Claude Opus 4.8).\n#\n# Reads LONGCAT_API_KEY from the environment first, then falls back to\n# ~/.zshrc / ~/.bashrc / ~/.bash_profile / ~/.profile if not already exported.\n#\n# Quick start (no install needed):\n# chmod +x lcclaude\n# ./lcclaude\n#\n# Optional — make it globally available:\n# sudo mv lcclaude /usr/local/bin/ && sudo chmod +x /usr/local/bin/lcclaude\n#\n# Use:\n# lcclaude # start on LongCat-2.0 (flagship)\n# lcclaude fast # start on LongCat-Flash-Chat (cheaper / faster)\n# lcclaude think # start on LongCat-Flash-Thinking (deep reasoning)\n# lcclaude long # request 1M context window (native support)\n# lcclaude effort max # set reasoning effort (low|medium|high|xhigh|max)\n# lcclaude update # git pull latest from this repo\n# lcclaude --help # any remaining flag is forwarded to claude\n#\n# Optional env overrides:\n# LONGCAT_MODEL=LongCat-2.0 # main model\n# LONGCAT_FLASH_MODEL=LongCat-Flash-Chat # flash / haiku / subagent tier\n# LONGCAT_BASE_URL=https://.../anthropic # custom Anthropic-compatible base URL\n# LONGCAT_CTX=1048576 # max context tokens (defaults to 1M with `long`)\n# LONGCAT_OUTPUT=8000 # cap output tokens\n# LONGCAT_EFFORT=max # CLAUDE_CODE_EFFORT_LEVEL\n#\n# In-session switch:\n# /model LongCat-Flash-Chat # switch to the fast tier\n# /model LongCat-Flash-Thinking # switch to thinking tier\n# /model LongCat-2.0 # switch back to flagship\n#\n# Get your free API key (public beta — 500K tokens/day free):\n# https://longcat.chat/platform\n#\nset -euo pipefail\n\n# Resolve symlink to find the real script directory.\n_SELF=\"$0\"\nif [ -L \"$_SELF\" ]; then\n _LINK=\"$(readlink \"$_SELF\")\"\n case \"$_LINK\" in\n /*) _SELF=\"$_LINK\" ;;\n *) _SELF=\"$(cd \"$(dirname \"$_SELF\")\" && pwd)/$_LINK\" ;;\n esac\nfi\nSELF_DIR=\"$(cd \"$(dirname \"$_SELF\")\" && pwd)\"\nif [ -f \"$SELF_DIR/lib/common.sh\" ]; then source \"$SELF_DIR/lib/common.sh\"\nelif [ -f \"$SELF_DIR/../lib/common.sh\" ]; then source \"$SELF_DIR/../lib/common.sh\"\nelse echo \"lcclaude: cannot find lib/common.sh. Reinstall or cd to repo.\" >&2; exit 1; fi\n\ncheck_version \"lcclaude\" \"$@\"\n\nPRO_MODEL=\"${LONGCAT_MODEL:-LongCat-2.0}\"\nFLASH_MODEL=\"${LONGCAT_FLASH_MODEL:-LongCat-Flash-Chat}\"\nTHINK_MODEL=\"${LONGCAT_THINK_MODEL:-LongCat-Flash-Thinking}\"\n\nif [ $# -gt 0 ] && [ \"$1\" = \"update\" ]; then\n do_update \"lcclaude\" \"LCCLAUDE_HOME\"\nfi\n\nAPI_KEY=\"$(resolve_api_key \"LONGCAT_API_KEY\")\"\nif [ -z \"$API_KEY\" ]; then\n echo \"❌ LONGCAT_API_KEY not found.\" >&2\n echo \" Add one line to ~/.zshrc or ~/.bashrc:\" >&2\n echo \" export LONGCAT_API_KEY=lc-xxxxxxxxxxxxxxxxxx\" >&2\n echo \" Get your free key at: https://longcat.chat/platform\" >&2\n exit 1\nfi\n\nBASE_URL=\"${LONGCAT_BASE_URL:-https://api.longcat.chat/anthropic}\"\n\nLONG_CTX=0\nEFFORT=\"${LONGCAT_EFFORT:-}\"\n\nMAIN_MODEL=\"$PRO_MODEL\"\nwhile [ $# -gt 0 ]; do\n case \"$1\" in\n fast|flash) MAIN_MODEL=\"$FLASH_MODEL\"; shift ;;\n think) MAIN_MODEL=\"$THINK_MODEL\"; shift ;;\n long) LONG_CTX=1; shift ;;\n effort)\n case \"${2:-}\" in\n low|medium|high|xhigh|max) EFFORT=\"$2\"; shift 2 ;;\n *) echo \"lcclaude: invalid effort level '${2:-}'. Use: low medium high xhigh max\" >&2; exit 1 ;;\n esac\n ;;\n --) shift; break ;;\n *) break ;;\n esac\ndone\n\n# Surface the other model in the /model picker.\nif [ \"$MAIN_MODEL\" = \"$PRO_MODEL\" ]; then\n OTHER_MODEL=\"$FLASH_MODEL\"\n OTHER_DESC=\"LongCat Flash Chat — fast / cheap tier\"\nelif [ \"$MAIN_MODEL\" = \"$FLASH_MODEL\" ]; then\n OTHER_MODEL=\"$PRO_MODEL\"\n OTHER_DESC=\"LongCat 2.0 — flagship reasoning\"\nelse\n OTHER_MODEL=\"$PRO_MODEL\"\n OTHER_DESC=\"LongCat 2.0 — flagship reasoning\"\nfi\n\nexport_anthropic_base\nexport CLAUDE_CODE_SUBAGENT_MODEL=\"$FLASH_MODEL\"\nset_custom_model \"$OTHER_MODEL\" \"$MAIN_MODEL\" \"$OTHER_DESC\"\n\nCTX=\"${LONGCAT_CTX:-}\"\nOUTPUT_CAP=\"${LONGCAT_OUTPUT:-}\"\napply_context_and_effort\n\nshow_banner_and_launch \"LongCat\" \"$@\"\n"}}, "lcclaude-desktop": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785674295.3671978, "n": 5919, "h": "f09c747bcb1a2087", "c": "#!/usr/bin/env bash\n# lcclaude-desktop — configure Claude Desktop to use Meituan LongCat as inference backend.\n#\n# Edits ~/Library/Application Support/Claude-3p/configLibrary/{_meta,<uuid>}.json\n# and restarts Claude Desktop. macOS only.\n#\n# Usage:\n# lcclaude-desktop # configure to LongCat-2.0 and restart\n# lcclaude-desktop update # git pull latest from the repo\n# lcclaude-desktop -h # help\n#\n# Reads LONGCAT_API_KEY from env or ~/.zshrc & friends (else prompts). The base URL\n# defaults to https://api.longcat.chat/anthropic; override with LONGCAT_BASE_URL.\n#\n# Get your free API key (public beta — 500K tokens/day free):\n# https://longcat.chat/platform\n#\n# Note: Once a third-party gateway is active, Claude Desktop's Chat mode is\n# unavailable — only Cowork (3P) and Code modes work.\n\nset -euo pipefail\n\nCONFIG_DIR=\"$HOME/Library/Application Support/Claude-3p/configLibrary\"\nMETA=\"$CONFIG_DIR/_meta.json\"\nENTRY_NAME=\"lcclaude-desktop\"\nAUTH_SCHEME=\"bearer\"\nMAIN_MODEL=\"LongCat-2.0\"\nFAST_MODEL=\"LongCat-Flash-Chat\"\nBASE_URL=\"${LONGCAT_BASE_URL:-https://api.longcat.chat/anthropic}\"\n\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n -h|--help)\n sed -n '2,20p' \"$0\" | sed 's/^# \\{0,1\\}//'\n exit 0\n ;;\n update)\n SELF_DIR=\"$(cd \"$(dirname \"$0\")\" && pwd)\"\n echo \"lcclaude-desktop: pulling latest from $SELF_DIR ...\"\n git -C \"$SELF_DIR\" pull && echo \"lcclaude-desktop: updated.\" || {\n echo \"lcclaude-desktop: git pull failed. Check network or resolve conflicts manually.\" >&2\n exit 1\n }\n exit 0\n ;;\n *)\n echo \"lcclaude-desktop: unknown argument: $1\" >&2\n echo \"Run 'lcclaude-desktop -h' for usage.\" >&2\n exit 2\n ;;\n esac\ndone\n\npreflight() {\n if [[ \"$(uname)\" != \"Darwin\" ]]; then\n echo \"lcclaude-desktop: macOS only.\" >&2\n exit 1\n fi\n if [[ ! -d \"/Applications/Claude.app\" ]]; then\n echo \"lcclaude-desktop: /Applications/Claude.app not found. Install from https://claude.ai/download.\" >&2\n exit 1\n fi\n if [[ ! -x \"/usr/bin/jq\" ]]; then\n echo \"lcclaude-desktop: /usr/bin/jq not found (required on macOS Sonoma+).\" >&2\n exit 1\n fi\n\n local dev_settings=\"$HOME/Library/Application Support/Claude/developer_settings.json\"\n if [[ ! -f \"$dev_settings\" ]] \\\n || ! /usr/bin/jq -e '.allowDevTools == true' \"$dev_settings\" >/dev/null 2>&1; then\n cat >&2 <<'EOF'\nlcclaude-desktop: Developer Mode not enabled in Claude Desktop.\n\nEnable it once in the GUI:\n 1. Open Claude Desktop\n 2. Help → Troubleshooting → Enable Developer Mode\n 3. Re-run lcclaude-desktop\nEOF\n exit 1\n fi\n}\n\nresolve_api_key() {\n if [[ -n \"${LONGCAT_API_KEY:-}\" ]]; then\n printf '%s' \"$LONGCAT_API_KEY\"\n return 0\n fi\n local rc found=\"\"\n for rc in \"$HOME/.zshrc\" \"$HOME/.bashrc\" \"$HOME/.bash_profile\" \"$HOME/.profile\"; do\n [[ -r \"$rc\" ]] || continue\n found=\"$(grep -v '^[[:space:]]*#' \"$rc\" 2>/dev/null \\\n | grep -E '^[[:space:]]*export[[:space:]]+LONGCAT_API_KEY=' \\\n | tail -1 \\\n | sed -E 's/^[^=]*=//; s/^\"(.*)\"$/\\1/; s/^'\\''(.*)'\\''$/\\1/' \\\n || true)\"\n if [[ -n \"$found\" ]]; then\n printf '%s' \"$found\"\n return 0\n fi\n done\n local key\n key=\"$(osascript <<'APPLESCRIPT' 2>/dev/null || true\ntry\n set theKey to text returned of (display dialog ¬\n \"LongCat API Key not found in env or shell rc.\\nPaste your LongCat API Key:\" ¬\n default answer \"\" ¬\n with hidden answer ¬\n with title \"lcclaude-desktop\")\n return theKey\non error\n return \"\"\nend try\nAPPLESCRIPT\n)\"\n if [[ -z \"$key\" ]]; then\n echo \"lcclaude-desktop: no LongCat API Key provided. Aborting.\" >&2\n exit 1\n fi\n printf '%s' \"$key\"\n}\n\nconfirm_or_abort() {\n echo\n echo \"About to: $1\"\n echo \"Press Enter to continue, Ctrl-C to abort.\"\n read -r _\n}\n\nwrite_entry() {\n local uuid=\"$1\"\n local entry_path=\"$CONFIG_DIR/${uuid}.json\"\n local tmp=\"${entry_path}.tmp\"\n local content\n content=\"$(jq -n \\\n --arg baseUrl \"$BASE_URL\" \\\n --arg apiKey \"$LC_KEY\" \\\n --arg auth \"$AUTH_SCHEME\" \\\n --arg main \"$MAIN_MODEL\" \\\n --arg fast \"$FAST_MODEL\" \\\n '{\n inferenceProvider: \"gateway\",\n inferenceGatewayBaseUrl: $baseUrl,\n inferenceGatewayApiKey: $apiKey,\n inferenceGatewayAuthScheme: $auth,\n unstableDisableModelVerification: true,\n inferenceModels: [\n {name: $main, supports1m: false},\n {name: $fast, supports1m: false}\n ]\n }')\"\n printf '%s' \"$content\" > \"$tmp\"\n chmod 600 \"$tmp\"\n mv \"$tmp\" \"$entry_path\"\n}\n\nensure_meta_entry() {\n mkdir -p \"$CONFIG_DIR\"\n local existing_uuid=\"\"\n if [[ -f \"$META\" ]]; then\n existing_uuid=\"$(jq -r --arg name \"$ENTRY_NAME\" \\\n '.entries[]? | select(.name==$name) | .id' \"$META\" 2>/dev/null \\\n | head -1)\"\n fi\n local uuid\n if [[ -n \"$existing_uuid\" ]]; then\n uuid=\"$existing_uuid\"\n else\n uuid=\"$(uuidgen | tr 'A-Z' 'a-z')\"\n fi\n local tmp=\"${META}.tmp\"\n local content\n if [[ -f \"$META\" ]]; then\n content=\"$(jq --arg id \"$uuid\" --arg name \"$ENTRY_NAME\" '\n .appliedId = $id\n | .entries = ((.entries // []) | map(select(.name != $name)) + [{id: $id, name: $name}])\n ' \"$META\")\"\n else\n content=\"$(jq -n --arg id \"$uuid\" --arg name \"$ENTRY_NAME\" \\\n '{appliedId: $id, entries: [{id: $id, name: $name}]}')\"\n fi\n printf '%s' \"$content\" > \"$tmp\"\n chmod 600 \"$tmp\"\n mv \"$tmp\" \"$META\"\n printf '%s' \"$uuid\"\n}\n\nrestart_claude() {\n killall Claude 2>/dev/null || true\n sleep 1\n open -a Claude\n}\n\npreflight\nLC_KEY=\"$(resolve_api_key)\"\nconfirm_or_abort \"configure Claude Desktop to use Meituan LongCat ($BASE_URL) and restart it.\"\nUUID=\"$(ensure_meta_entry)\"\nwrite_entry \"$UUID\"\nrestart_claude\n\ncat <<'EOF'\n\nDone. Claude Desktop is restarting with Meituan LongCat as the inference backend.\n\nHeads up: Chat mode is unavailable while a third-party gateway is active.\nRe-run lcclaude-desktop any time to refresh the gateway config.\nEOF\n"}}, "lcclaude.ps1": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785674295.8456082, "n": 7939, "h": "7aa1c9086ff26528", "c": "#!/usr/bin/env pwsh\n# lcclaude.ps1 — launch Claude Code on Meituan LongCat's Anthropic-compatible API (Windows port).\n#\n# Windows companion to the macOS/Linux bash script `lcclaude`. Same env vars,\n# same model picker — different shell.\n#\n# Uses the official LongCat Anthropic-compatible endpoint:\n# https://api.longcat.chat/anthropic\n#\n# Reads LONGCAT_API_KEY from the process env first, then User/Machine env vars.\n#\n# Quick start (from the lcclaude directory):\n# pwsh -File .\\lcclaude.ps1\n#\n# Three invocation rules that matter on Windows:\n# 1. Use `pwsh`, not `powershell`.\n# 2. Use `-File`, not `-Command` / `&`.\n# 3. Allow local scripts to run (one-time):\n# Set-ExecutionPolicy -Scope CurrentUser RemoteSigned\n#\n# Use:\n# pwsh -File ./lcclaude.ps1 # LongCat-2.0 (flagship)\n# pwsh -File ./lcclaude.ps1 fast # LongCat-Flash-Chat\n# pwsh -File ./lcclaude.ps1 think # LongCat-Flash-Thinking\n# pwsh -File ./lcclaude.ps1 long # request 1M context window\n# pwsh -File ./lcclaude.ps1 effort max # set effort (low|medium|high|xhigh|max)\n# pwsh -File ./lcclaude.ps1 update # git pull\n# pwsh -File ./lcclaude.ps1 --help # forwarded to claude\n#\n# Optional env overrides:\n# $env:LONGCAT_MODEL = 'LongCat-2.0' # main model\n# $env:LONGCAT_FLASH_MODEL = 'LongCat-Flash-Chat' # flash tier\n# $env:LONGCAT_BASE_URL = 'https://.../anthropic'\n# $env:LONGCAT_CTX = '1048576' # max context tokens\n# $env:LONGCAT_OUTPUT = '8000' # cap output tokens\n# $env:LONGCAT_EFFORT = 'max' # CLAUDE_CODE_EFFORT_LEVEL\n#\n# In-session switch:\n# /model LongCat-Flash-Chat # fast tier\n# /model LongCat-Flash-Thinking # thinking tier\n# /model LongCat-2.0 # flagship\n#\n# Get your free API key: https://longcat.chat/platform\n\n[CmdletBinding()]\nparam(\n [Parameter(ValueFromRemainingArguments = $true)]\n [string[]]$Rest\n)\n\n$ErrorActionPreference = 'Stop'\n\nif ($PSVersionTable.PSVersion.Major -lt 7) {\n Write-Error @\"\nlcclaude.ps1: PowerShell 7+ required (you're on $($PSVersionTable.PSVersion)).\n\nWindows PowerShell 5.1 cannot host claude's interactive UI.\nInstall PowerShell 7 once:\n\n winget install Microsoft.PowerShell\n\nThen re-run with:\n\n pwsh -File .\\lcclaude.ps1\n\"@\n exit 1\n}\n\n# ---- Self-update -----------------------------------------------------------\n\nfunction Invoke-LcclaudeUpdate {\n $repo = $null\n $selfDir = Split-Path -Parent $PSCommandPath\n if (Test-Path (Join-Path $selfDir '.git')) { $repo = $selfDir }\n if (-not $repo -and $env:LCCLAUDE_HOME) { $repo = $env:LCCLAUDE_HOME }\n if (-not $repo) {\n $candidate = Join-Path $env:USERPROFILE 'github\\xxclaude'\n if (Test-Path (Join-Path $candidate '.git')) { $repo = $candidate }\n }\n if (-not $repo) {\n Write-Error @'\nlcclaude: cannot find the xxclaude repo for self-update.\n Set $env:LCCLAUDE_HOME = 'C:\\path\\to\\xxclaude' or cd into the repo and run pwsh -File ./lcclaude.ps1 update\n'@\n exit 1\n }\n Write-Host \"lcclaude: pulling latest from $repo ...\"\n git -C $repo pull\n if ($LASTEXITCODE -ne 0) {\n Write-Error 'lcclaude: git pull failed. Check network or resolve conflicts manually.'\n exit 1\n }\n Write-Host 'lcclaude: updated.'\n exit 0\n}\n\n# ---- API key resolution ----------------------------------------------------\n\nfunction Resolve-ApiKey {\n if ($env:LONGCAT_API_KEY) { return $env:LONGCAT_API_KEY }\n foreach ($scope in 'User', 'Machine') {\n $v = [Environment]::GetEnvironmentVariable('LONGCAT_API_KEY', $scope)\n if ($v) { return $v }\n }\n Write-Error @'\nLONGCAT_API_KEY not found.\n Set it persistently (User scope, takes effect in new shells):\n setx LONGCAT_API_KEY \"lc-xxxxxxxxxxxxxxxxxx\"\n Or for the current shell only:\n $env:LONGCAT_API_KEY = 'lc-xxxxxxxxxxxxxxxxxx'\n Get your free key at: https://longcat.chat/platform\n'@\n exit 1\n}\n\n# ---- Arg parsing -----------------------------------------------------------\n\n$mainModel = $null\n$LongCtx = $false\n$Effort = if ($env:LONGCAT_EFFORT) { $env:LONGCAT_EFFORT } else { '' }\n\n$remaining = @()\n$rest = @($Rest)\n$i = 0\n:argloop while ($i -lt $rest.Count) {\n $a = $rest[$i]\n switch -CaseSensitive ($a) {\n 'update' { Invoke-LcclaudeUpdate }\n 'fast' { $mainModel = 'LongCat-Flash-Chat'; $i++; break }\n 'flash' { $mainModel = 'LongCat-Flash-Chat'; $i++; break }\n 'think' { $mainModel = 'LongCat-Flash-Thinking'; $i++; break }\n 'long' { $LongCtx = $true; $i++; break }\n 'effort' {\n $i++; if ($i -lt $rest.Count) { $l=$rest[$i]; if ($l -in 'low','medium','high','xhigh','max'){$Effort=$l;$i++;break}else{Write-Error \"lcclaude: invalid effort level '$l'. Use: low medium high xhigh max\";exit 1}}else{Write-Error \"lcclaude: 'effort' requires a level: low medium high xhigh max\";exit 1}\n }\n '--' {\n $i++\n if ($i -lt $rest.Count) { $remaining += $rest[$i..($rest.Count - 1)] }\n break argloop\n }\n default {\n $remaining += $rest[$i..($rest.Count - 1)]\n break argloop\n }\n }\n}\n\n$apiKey = Resolve-ApiKey\n\n$baseUrl = if ($env:LONGCAT_BASE_URL) { $env:LONGCAT_BASE_URL } else { 'https://api.longcat.chat/anthropic' }\n$proModel = if ($env:LONGCAT_MODEL) { $env:LONGCAT_MODEL } else { 'LongCat-2.0' }\n$flashModel = if ($env:LONGCAT_FLASH_MODEL) { $env:LONGCAT_FLASH_MODEL } else { 'LongCat-Flash-Chat' }\n$thinkModel = if ($env:LONGCAT_THINK_MODEL) { $env:LONGCAT_THINK_MODEL } else { 'LongCat-Flash-Thinking' }\n\nif (-not $mainModel) { $mainModel = $proModel }\n\nif ($mainModel -eq $proModel) {\n $otherModel = $flashModel\n $otherDesc = 'LongCat Flash Chat — fast / cheap tier'\n} elseif ($mainModel -eq $flashModel) {\n $otherModel = $proModel\n $otherDesc = 'LongCat 2.0 — flagship reasoning'\n} else {\n $otherModel = $proModel\n $otherDesc = 'LongCat 2.0 — flagship reasoning'\n}\n\n# ---- Export env for claude -------------------------------------------------\n\n$env:ANTHROPIC_API_KEY = $null\n\n$env:ANTHROPIC_BASE_URL = $baseUrl\n$env:ANTHROPIC_AUTH_TOKEN = $apiKey\n$env:ANTHROPIC_MODEL = $mainModel\n$env:ANTHROPIC_DEFAULT_OPUS_MODEL = $mainModel\n$env:ANTHROPIC_DEFAULT_SONNET_MODEL = $mainModel\n$env:ANTHROPIC_DEFAULT_HAIKU_MODEL = $flashModel\n$env:CLAUDE_CODE_SUBAGENT_MODEL = $flashModel\n\nif ($otherModel -ne $mainModel) {\n $env:ANTHROPIC_CUSTOM_MODEL_OPTION = $otherModel\n $env:ANTHROPIC_CUSTOM_MODEL_OPTION_NAME = $otherModel\n $env:ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION = $otherDesc\n}\n\n# ---- Effort level ----------------------------------------------------------\nif ($Effort) { $env:CLAUDE_CODE_EFFORT_LEVEL = $Effort }\n# ---- Context window --------------------------------------------------------\n$ctx = if ($env:LONGCAT_CTX) { $env:LONGCAT_CTX } elseif ($LongCtx) { '1048576' } else { '' }\nif ($ctx) { $env:CLAUDE_CODE_MAX_CONTEXT_TOKENS = $ctx; $env:DISABLE_COMPACT = '1' }\n# ---- Output cap ------------------------------------------------------------\nif ($env:LONGCAT_OUTPUT) { $env:CLAUDE_CODE_MAX_OUTPUT_TOKENS = $env:LONGCAT_OUTPUT }\n\n# ---- Launch ----------------------------------------------------------------\n\nif (-not (Get-Command claude -ErrorAction SilentlyContinue)) {\n Write-Error @'\nlcclaude: `claude` CLI not found on PATH.\n Install Claude Code: npm install -g @anthropic-ai/claude-code\n Then re-run this script.\n'@\n exit 1\n}\n\n$banner = \"🚀 Claude Code on LongCat → $mainModel ($baseUrl)\"\nif ($ctx) { $banner += \" | ctx=$ctx\" }\nif ($Effort) { $banner += \" | effort=$Effort\" }\nif ($otherModel -ne $mainModel) { $banner += ' (switch mid-session via /model)' }\nWrite-Host $banner\n\n& claude @remaining\nexit $LASTEXITCODE\n"}}, "lcclaude-desktop.ps1": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785674297.4378116, "n": 8643, "h": "dd5b3cfe45637e15", "c": "#!/usr/bin/env pwsh\n# lcclaude-desktop.ps1 — configure Claude Desktop to use Meituan LongCat (Windows port).\n#\n# Usage:\n# pwsh ./lcclaude-desktop.ps1 # auto-detect and configure\n# pwsh ./lcclaude-desktop.ps1 -ClaudeExePath <path> # specify custom Claude.exe\n# pwsh ./lcclaude-desktop.ps1 -Update # git pull\n# pwsh ./lcclaude-desktop.ps1 -h # help\n#\n# Reads LONGCAT_API_KEY from env (else prompts). Base URL defaults to\n# https://api.longcat.chat/anthropic; override with $env:LONGCAT_BASE_URL.\n#\n# Get your free API key: https://longcat.chat/platform\n\n[CmdletBinding()]\nparam(\n [Alias('h')][switch]$Help,\n [switch]$Update,\n [string]$ClaudeExePath\n)\n\n$ErrorActionPreference = 'Stop'\n\n$ConfigDir = Join-Path $env:LOCALAPPDATA 'Claude-3p\\configLibrary'\n$Meta = Join-Path $ConfigDir '_meta.json'\n$StoreDir = if (Get-ChildItem \"$env:LOCALAPPDATA\\Packages\\Claude_*\" -ErrorAction SilentlyContinue) {\n Join-Path (Resolve-Path \"$env:LOCALAPPDATA\\Packages\\Claude_*\") 'LocalCache\\Roaming\\Claude-3p\\configLibrary'\n } else { $null }\n$EntryName = 'lcclaude-desktop'\n$AuthScheme = 'bearer'\n$MainModel = 'LongCat-2.0'\n$FastModel = 'LongCat-Flash-Chat'\n$BaseUrl = if ($env:LONGCAT_BASE_URL) { $env:LONGCAT_BASE_URL } else { 'https://api.longcat.chat/anthropic' }\n\n$ClaudeExe = $null\n\nif ($Help) {\n Get-Content $PSCommandPath | Select-Object -Skip 1 -First 15 |\n ForEach-Object { $_ -replace '^# ?', '' }\n exit 0\n}\n\nif ($Update) {\n $repo = Split-Path -Parent $PSCommandPath\n Write-Host \"lcclaude-desktop: pulling latest from $repo ...\"\n git -C $repo pull\n if ($LASTEXITCODE -eq 0) { Write-Host 'lcclaude-desktop: updated.' }\n else { Write-Error 'lcclaude-desktop: git pull failed.'; exit 1 }\n exit 0\n}\n\n# ---- Pre-flight ------------------------------------------------------------\n\nfunction Test-Preflight {\n $isWin = if ($null -ne $IsWindows) { $IsWindows } else { $true }\n if (-not $isWin) {\n Write-Error 'lcclaude-desktop.ps1: Windows only. Use ./lcclaude-desktop on macOS.'\n exit 1\n }\n\n if ($script:ClaudeExePath) {\n if (-not (Test-Path $script:ClaudeExePath)) {\n Write-Error \"lcclaude-desktop.ps1: Claude.exe not found at '$script:ClaudeExePath'\"\n exit 1\n }\n $script:ClaudeExe = $script:ClaudeExePath\n } else {\n $candidates = @()\n $pkg = Get-AppxPackage -Name 'Claude*' -ErrorAction SilentlyContinue | Select-Object -First 1\n if ($pkg) { $candidates += Join-Path $pkg.InstallLocation 'app\\claude.exe' }\n\n $packagesBase = Join-Path $env:LOCALAPPDATA 'Packages'\n if (Test-Path $packagesBase) {\n $candidates += Get-ChildItem -Path $packagesBase -Directory -Filter 'Claude_*' -ErrorAction SilentlyContinue |\n ForEach-Object { Join-Path $_.FullName 'LocalCache\\Local\\Claude-3p\\claude-code\\*\\claude.exe' } |\n ForEach-Object { Get-ChildItem -Path $_ -ErrorAction SilentlyContinue } |\n Select-Object -ExpandProperty FullName\n }\n $candidates += @(\n (Join-Path $env:LOCALAPPDATA 'AnthropicClaude\\Claude.exe'),\n (Join-Path $env:LOCALAPPDATA 'Programs\\AnthropicClaude\\Claude.exe'),\n (Join-Path ${env:ProgramFiles} 'AnthropicClaude\\Claude.exe'),\n (Join-Path ${env:ProgramFiles(x86)} 'AnthropicClaude\\Claude.exe')\n )\n $found = $candidates | Where-Object { Test-Path $_ } | Select-Object -First 1\n if (-not $found) {\n Write-Error \"lcclaude-desktop.ps1: Claude Desktop not found. Install from https://claude.ai/download\"\n exit 1\n }\n $script:ClaudeExe = $found\n }\n\n $devSettings = Join-Path $env:APPDATA 'Claude\\developer_settings.json'\n $devDir = Split-Path $devSettings -Parent\n $needsEnable = $false\n if (Test-Path $devSettings) {\n $dev = Get-Content $devSettings -Raw | ConvertFrom-Json\n if (-not $dev.allowDevTools) { $needsEnable = $true }\n } else { $needsEnable = $true }\n if ($needsEnable) {\n Write-Host 'lcclaude-desktop.ps1: Enabling Developer Mode for Claude Desktop...'\n if (-not (Test-Path $devDir)) { New-Item -ItemType Directory -Path $devDir -Force | Out-Null }\n $devContent = '{ \"allowDevTools\": true }'\n [System.IO.File]::WriteAllText($devSettings, $devContent, [System.Text.UTF8Encoding]::new($false))\n Write-Host 'lcclaude-desktop.ps1: Developer Mode enabled.'\n }\n}\n\n# ---- API key resolution ----------------------------------------------------\n\nfunction Resolve-ApiKey {\n if ($env:LONGCAT_API_KEY) { return $env:LONGCAT_API_KEY }\n foreach ($scope in 'User', 'Machine') {\n $v = [Environment]::GetEnvironmentVariable('LONGCAT_API_KEY', $scope)\n if ($v) { return $v }\n }\n $secure = Read-Host 'LONGCAT_API_KEY not set. Paste your LongCat API Key' -AsSecureString\n if (-not $secure -or $secure.Length -eq 0) {\n Write-Error 'lcclaude-desktop.ps1: no LongCat API Key provided. Aborting.'\n exit 1\n }\n $bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secure)\n try { return [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr) }\n finally { [System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) }\n}\n\nfunction Confirm-OrAbort { param([string]$Action); Write-Host ''; Write-Host \"About to: $Action\"; [void](Read-Host 'Press Enter to continue, Ctrl-C to abort') }\n\nfunction Write-JsonAtomic {\n param([string]$Path, $Object)\n $json = $Object | ConvertTo-Json -Depth 6\n $json = $json.TrimEnd(\"`r\", \"`n\")\n $tmp = \"$Path.tmp\"\n [System.IO.File]::WriteAllText($tmp, $json, [System.Text.UTF8Encoding]::new($false))\n Move-Item -Path $tmp -Destination $Path -Force\n}\n\nfunction Update-MetaEntry {\n $dirs = @($script:ConfigDir) + @(if ($script:StoreDir) { $script:StoreDir } else { @() })\n foreach ($d in $dirs) { if (-not (Test-Path $d)) { New-Item -ItemType Directory -Path $d -Force | Out-Null } }\n $existingUuid = $null\n $metaPath = Join-Path $dirs[0] '_meta.json'\n if (Test-Path $metaPath) {\n $existing = Get-Content $metaPath -Raw | ConvertFrom-Json\n $existingUuid = ($existing.entries | Where-Object { $_.name -eq $script:EntryName } | Select-Object -First 1).id\n }\n $uuid = if ($existingUuid) { $existingUuid } else { [guid]::NewGuid().ToString().ToLower() }\n $entries = @()\n if (Test-Path $metaPath) {\n $existing = Get-Content $metaPath -Raw | ConvertFrom-Json\n $entries = @($existing.entries | Where-Object { $_.name -ne $script:EntryName })\n }\n $entries += [pscustomobject]@{ id = $uuid; name = $script:EntryName }\n $newMeta = [ordered]@{ appliedId = $uuid; entries = @($entries) }\n foreach ($d in $dirs) { Write-JsonAtomic -Path (Join-Path $d '_meta.json') -Object $newMeta }\n return $uuid\n}\n\nfunction Write-Entry {\n param([string]$Uuid, [string]$ApiKey)\n $entry = [ordered]@{\n inferenceProvider = 'gateway'\n inferenceGatewayBaseUrl = $script:BaseUrl\n inferenceGatewayApiKey = $ApiKey\n inferenceGatewayAuthScheme = $AuthScheme\n unstableDisableModelVerification = $true\n inferenceModels = @(\n [ordered]@{ name = $MainModel; supports1m = $false },\n [ordered]@{ name = $FastModel; supports1m = $false }\n )\n }\n $dirs = @($script:ConfigDir) + @(if ($script:StoreDir) { $script:StoreDir } else { @() })\n foreach ($d in $dirs) { Write-JsonAtomic -Path (Join-Path $d \"$Uuid.json\") -Object $entry }\n}\n\nfunction Restart-Claude {\n Get-CimInstance Win32_Process -Filter \"Name='claude.exe'\" -ErrorAction SilentlyContinue |\n Where-Object { $_.CommandLine -like \"*$($script:ClaudeExe)*\" } |\n ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }\n Start-Sleep -Seconds 1\n Start-Process -FilePath $script:ClaudeExe\n}\n\n# ---- Main ------------------------------------------------------------------\n\nTest-Preflight\n$apiKey = Resolve-ApiKey\nConfirm-OrAbort -Action \"configure Claude Desktop to use Meituan LongCat ($script:BaseUrl) and restart it.\"\n$uuid = Update-MetaEntry\nWrite-Entry -Uuid $uuid -ApiKey $apiKey\nRestart-Claude\n\n@\"\n\nDone. Claude Desktop is restarting with Meituan LongCat as the inference backend.\n\nHeads up: Chat mode is unavailable while a third-party gateway is active.\nRe-run lcclaude-desktop.ps1 any time to refresh the gateway config.\n\"@ | Write-Host\n"}}, "install.sh": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785745936.9618356, "n": 3613, "h": "552c7ddbbfeb270d", "c": "#!/usr/bin/env bash\n# install.sh — one-command installer for dsclaude launchers.\n#\n# Usage:\n# curl -fsSL https://raw.githubusercontent.com/Agents365-ai/dsclaude/main/install.sh | bash\n#\n# # Or, if you already have the repo:\n# ./install.sh\n#\n# # Install to ~/.local/bin instead of /usr/local/bin:\n# curl ... | bash -s -- --user\n#\n# # Custom install directory:\n# ./install.sh --prefix /opt/bin\n#\nset -euo pipefail\n\nPREFIX=\"\"\nREPO_URL=\"https://github.com/Agents365-ai/dsclaude.git\"\nTMP_DIR=\"\"\n\ncleanup() { [ -n \"${TMP_DIR:-}\" ] && rm -rf \"$TMP_DIR\"; }\ntrap cleanup EXIT\n\n# ---- Parse args ------------------------------------------------------------\nwhile [ $# -gt 0 ]; do\n case \"$1\" in\n --user) PREFIX=\"$HOME/.local/bin\" ;;\n --prefix) PREFIX=\"$2\"; shift ;;\n *) echo \"install.sh: unknown option: $1\" >&2; exit 1 ;;\n esac\n shift\ndone\n\n# ---- Resolve install directory ---------------------------------------------\nif [ -z \"$PREFIX\" ]; then\n if [ -w /usr/local/bin ]; then\n PREFIX=\"/usr/local/bin\"\n elif [ \"$(id -u)\" = \"0\" ]; then\n PREFIX=\"/usr/local/bin\"\n else\n echo \"install.sh: /usr/local/bin is not writable. Options:\"\n echo \" • Run with sudo: curl ... | sudo bash\"\n echo \" • User install: curl ... | bash -s -- --user\"\n exit 1\n fi\nfi\n\nmkdir -p \"$PREFIX\"\n\necho \"install.sh: installing to $PREFIX\"\n\n# ---- Get the scripts -------------------------------------------------------\nREPO_DIR=\"\"\n# If we're already inside a repo clone, use it directly.\nself_dir=\"$(cd \"$(dirname \"$0\")\" 2>/dev/null && pwd || true)\"\nif [ -n \"${self_dir:-}\" ] && [ -f \"$self_dir/dsclaude\" ] && [ -d \"$self_dir/.git\" ]; then\n REPO_DIR=\"$self_dir\"\n echo \"install.sh: using local repo at $REPO_DIR\"\nelse\n TMP_DIR=\"$(mktemp -d -t dsclaude-install.XXXXXX)\"\n echo \"install.sh: cloning $REPO_URL ...\"\n git clone --depth 1 \"$REPO_URL\" \"$TMP_DIR\" >/dev/null 2>&1 || {\n echo \"install.sh: git clone failed. Check your network or install git.\" >&2\n exit 1\n }\n REPO_DIR=\"$TMP_DIR\"\nfi\n\n# ---- Install shared library --------------------------------------------------\necho \"install.sh: installing shared library...\"\nmkdir -p \"$PREFIX/lib\"\ncp \"$REPO_DIR/lib/common.sh\" \"$PREFIX/lib/common.sh\"\nchmod +x \"$PREFIX/lib/common.sh\"\n\n# ---- Install CLI launchers (no extension) ----------------------------------\ncount=0\necho \"install.sh: installing CLI launchers...\"\nfor script in \"$REPO_DIR\"/*claude; do\n name=\"$(basename \"$script\")\"\n # Skip .ps1 files and desktop configurators.\n case \"$name\" in\n *.ps1|*-desktop) continue ;;\n esac\n # Skip non-files.\n [ ! -f \"$script\" ] && continue\n cp \"$script\" \"$PREFIX/$name\"\n chmod +x \"$PREFIX/$name\"\n echo \" $name\"\n count=$((count + 1))\ndone\n\n# ---- Install desktop configurators -----------------------------------------\necho \"install.sh: installing desktop configurators...\"\nfor script in \"$REPO_DIR\"/*-desktop; do\n name=\"$(basename \"$script\")\"\n [ ! -f \"$script\" ] && continue\n cp \"$script\" \"$PREFIX/$name\"\n chmod +x \"$PREFIX/$name\"\n echo \" $name\"\n count=$((count + 1))\ndone\n\necho \"\"\necho \"✓ Installed $count scripts to $PREFIX\"\n\n# ---- PATH reminder ----------------------------------------------------------\nif [ \"$PREFIX\" = \"$HOME/.local/bin\" ]; then\n if ! echo \"$PATH\" | tr ':' '\\n' | grep -qFx \"$PREFIX\"; then\n echo \"\"\n echo \"⚠️ $PREFIX is not in your PATH. Add this to your ~/.zshrc or ~/.bashrc:\"\n echo \" export PATH=\\\"\\$HOME/.local/bin:\\$PATH\\\"\"\n fi\nfi\n\necho \"\"\necho \"Now set an API key and run xclaude (auto-detect) or any launcher directly:\"\necho \" export DEEPSEEK_API_KEY=sk-...\"\necho \" xclaude\"\n"}, "a8b31904f7f4db6cf2d9821361c59048c9e26687": {"t": 1785758056.182733, "n": 3613, "h": "552c7ddbbfeb270d", "c": "#!/usr/bin/env bash\n# install.sh — one-command installer for dsclaude launchers.\n#\n# Usage:\n# curl -fsSL https://raw.githubusercontent.com/Agents365-ai/dsclaude/main/install.sh | bash\n#\n# # Or, if you already have the repo:\n# ./install.sh\n#\n# # Install to ~/.local/bin instead of /usr/local/bin:\n# curl ... | bash -s -- --user\n#\n# # Custom install directory:\n# ./install.sh --prefix /opt/bin\n#\nset -euo pipefail\n\nPREFIX=\"\"\nREPO_URL=\"https://github.com/Agents365-ai/dsclaude.git\"\nTMP_DIR=\"\"\n\ncleanup() { [ -n \"${TMP_DIR:-}\" ] && rm -rf \"$TMP_DIR\"; }\ntrap cleanup EXIT\n\n# ---- Parse args ------------------------------------------------------------\nwhile [ $# -gt 0 ]; do\n case \"$1\" in\n --user) PREFIX=\"$HOME/.local/bin\" ;;\n --prefix) PREFIX=\"$2\"; shift ;;\n *) echo \"install.sh: unknown option: $1\" >&2; exit 1 ;;\n esac\n shift\ndone\n\n# ---- Resolve install directory ---------------------------------------------\nif [ -z \"$PREFIX\" ]; then\n if [ -w /usr/local/bin ]; then\n PREFIX=\"/usr/local/bin\"\n elif [ \"$(id -u)\" = \"0\" ]; then\n PREFIX=\"/usr/local/bin\"\n else\n echo \"install.sh: /usr/local/bin is not writable. Options:\"\n echo \" • Run with sudo: curl ... | sudo bash\"\n echo \" • User install: curl ... | bash -s -- --user\"\n exit 1\n fi\nfi\n\nmkdir -p \"$PREFIX\"\n\necho \"install.sh: installing to $PREFIX\"\n\n# ---- Get the scripts -------------------------------------------------------\nREPO_DIR=\"\"\n# If we're already inside a repo clone, use it directly.\nself_dir=\"$(cd \"$(dirname \"$0\")\" 2>/dev/null && pwd || true)\"\nif [ -n \"${self_dir:-}\" ] && [ -f \"$self_dir/dsclaude\" ] && [ -d \"$self_dir/.git\" ]; then\n REPO_DIR=\"$self_dir\"\n echo \"install.sh: using local repo at $REPO_DIR\"\nelse\n TMP_DIR=\"$(mktemp -d -t dsclaude-install.XXXXXX)\"\n echo \"install.sh: cloning $REPO_URL ...\"\n git clone --depth 1 \"$REPO_URL\" \"$TMP_DIR\" >/dev/null 2>&1 || {\n echo \"install.sh: git clone failed. Check your network or install git.\" >&2\n exit 1\n }\n REPO_DIR=\"$TMP_DIR\"\nfi\n\n# ---- Install shared library --------------------------------------------------\necho \"install.sh: installing shared library...\"\nmkdir -p \"$PREFIX/lib\"\ncp \"$REPO_DIR/lib/common.sh\" \"$PREFIX/lib/common.sh\"\nchmod +x \"$PREFIX/lib/common.sh\"\n\n# ---- Install CLI launchers (no extension) ----------------------------------\ncount=0\necho \"install.sh: installing CLI launchers...\"\nfor script in \"$REPO_DIR\"/*claude; do\n name=\"$(basename \"$script\")\"\n # Skip .ps1 files and desktop configurators.\n case \"$name\" in\n *.ps1|*-desktop) continue ;;\n esac\n # Skip non-files.\n [ ! -f \"$script\" ] && continue\n cp \"$script\" \"$PREFIX/$name\"\n chmod +x \"$PREFIX/$name\"\n echo \" $name\"\n count=$((count + 1))\ndone\n\n# ---- Install desktop configurators -----------------------------------------\necho \"install.sh: installing desktop configurators...\"\nfor script in \"$REPO_DIR\"/*-desktop; do\n name=\"$(basename \"$script\")\"\n [ ! -f \"$script\" ] && continue\n cp \"$script\" \"$PREFIX/$name\"\n chmod +x \"$PREFIX/$name\"\n echo \" $name\"\n count=$((count + 1))\ndone\n\necho \"\"\necho \"✓ Installed $count scripts to $PREFIX\"\n\n# ---- PATH reminder ----------------------------------------------------------\nif [ \"$PREFIX\" = \"$HOME/.local/bin\" ]; then\n if ! echo \"$PATH\" | tr ':' '\\n' | grep -qFx \"$PREFIX\"; then\n echo \"\"\n echo \"⚠️ $PREFIX is not in your PATH. Add this to your ~/.zshrc or ~/.bashrc:\"\n echo \" export PATH=\\\"\\$HOME/.local/bin:\\$PATH\\\"\"\n fi\nfi\n\necho \"\"\necho \"Now set an API key and run xclaude (auto-detect) or any launcher directly:\"\necho \" export DEEPSEEK_API_KEY=sk-...\"\necho \" xclaude\"\n"}, "2525882659f2c26f4e2221ba062878ff8234b7c3": {"t": 1785758058.1636488, "n": 3374, "h": "2e22cedcbdae5aa5", "c": "#!/usr/bin/env bash\n# install.sh — one-command installer for dsclaude launchers.\n#\n# Usage:\n# curl -fsSL https://raw.githubusercontent.com/Agents365-ai/dsclaude/main/install.sh | bash\n#\n# # Or, if you already have the repo:\n# ./install.sh\n#\n# # Install to ~/.local/bin instead of /usr/local/bin:\n# curl ... | bash -s -- --user\n#\n# # Custom install directory:\n# ./install.sh --prefix /opt/bin\n#\nset -euo pipefail\n\nPREFIX=\"\"\nREPO_URL=\"https://github.com/Agents365-ai/dsclaude.git\"\nTMP_DIR=\"\"\n\ncleanup() { [ -n \"${TMP_DIR:-}\" ] && rm -rf \"$TMP_DIR\"; }\ntrap cleanup EXIT\n\n# ---- Parse args ------------------------------------------------------------\nwhile [ $# -gt 0 ]; do\n case \"$1\" in\n --user) PREFIX=\"$HOME/.local/bin\" ;;\n --prefix) PREFIX=\"$2\"; shift ;;\n *) echo \"install.sh: unknown option: $1\" >&2; exit 1 ;;\n esac\n shift\ndone\n\n# ---- Resolve install directory ---------------------------------------------\nif [ -z \"$PREFIX\" ]; then\n if [ -w /usr/local/bin ]; then\n PREFIX=\"/usr/local/bin\"\n elif [ \"$(id -u)\" = \"0\" ]; then\n PREFIX=\"/usr/local/bin\"\n else\n echo \"install.sh: /usr/local/bin is not writable. Options:\"\n echo \" • Run with sudo: curl ... | sudo bash\"\n echo \" • User install: curl ... | bash -s -- --user\"\n exit 1\n fi\nfi\n\nmkdir -p \"$PREFIX\"\n\necho \"install.sh: installing to $PREFIX\"\n\n# ---- Get the scripts -------------------------------------------------------\nREPO_DIR=\"\"\n# If we're already inside a repo clone, use it directly.\nself_dir=\"$(cd \"$(dirname \"$0\")\" 2>/dev/null && pwd || true)\"\nif [ -n \"${self_dir:-}\" ] && [ -f \"$self_dir/dsclaude\" ] && [ -d \"$self_dir/.git\" ]; then\n REPO_DIR=\"$self_dir\"\n echo \"install.sh: using local repo at $REPO_DIR\"\nelse\n TMP_DIR=\"$(mktemp -d -t dsclaude-install.XXXXXX)\"\n echo \"install.sh: cloning $REPO_URL ...\"\n git clone --depth 1 \"$REPO_URL\" \"$TMP_DIR\" >/dev/null 2>&1 || {\n echo \"install.sh: git clone failed. Check your network or install git.\" >&2\n exit 1\n }\n REPO_DIR=\"$TMP_DIR\"\nfi\n\n# ---- Install CLI launchers (no extension) ----------------------------------\ncount=0\necho \"install.sh: installing CLI launchers...\"\nfor script in \"$REPO_DIR\"/*claude; do\n name=\"$(basename \"$script\")\"\n # Skip .ps1 files and desktop configurators.\n case \"$name\" in\n *.ps1|*-desktop) continue ;;\n esac\n # Skip non-files.\n [ ! -f \"$script\" ] && continue\n cp \"$script\" \"$PREFIX/$name\"\n chmod +x \"$PREFIX/$name\"\n echo \" $name\"\n count=$((count + 1))\ndone\n\n# ---- Install desktop configurators -----------------------------------------\necho \"install.sh: installing desktop configurators...\"\nfor script in \"$REPO_DIR\"/*-desktop; do\n name=\"$(basename \"$script\")\"\n [ ! -f \"$script\" ] && continue\n cp \"$script\" \"$PREFIX/$name\"\n chmod +x \"$PREFIX/$name\"\n echo \" $name\"\n count=$((count + 1))\ndone\n\necho \"\"\necho \"✓ Installed $count scripts to $PREFIX\"\n\n# ---- PATH reminder ----------------------------------------------------------\nif [ \"$PREFIX\" = \"$HOME/.local/bin\" ]; then\n if ! echo \"$PATH\" | tr ':' '\\n' | grep -qFx \"$PREFIX\"; then\n echo \"\"\n echo \"⚠️ $PREFIX is not in your PATH. Add this to your ~/.zshrc or ~/.bashrc:\"\n echo \" export PATH=\\\"\\$HOME/.local/bin:\\$PATH\\\"\"\n fi\nfi\n\necho \"\"\necho \"Now set an API key and run xclaude (auto-detect) or any launcher directly:\"\necho \" export DEEPSEEK_API_KEY=sk-...\"\necho \" xclaude\"\n"}, "c771390e6deb25702c6665ad8e0e4427e068b15a": {"t": 1785758060.071504, "n": 3374, "h": "fdda6b535b4645ac", "c": "#!/usr/bin/env bash\n# install.sh — one-command installer for xxclaude launchers.\n#\n# Usage:\n# curl -fsSL https://raw.githubusercontent.com/Agents365-ai/dsclaude/main/install.sh | bash\n#\n# # Or, if you already have the repo:\n# ./install.sh\n#\n# # Install to ~/.local/bin instead of /usr/local/bin:\n# curl ... | bash -s -- --user\n#\n# # Custom install directory:\n# ./install.sh --prefix /opt/bin\n#\nset -euo pipefail\n\nPREFIX=\"\"\nREPO_URL=\"https://github.com/Agents365-ai/dsclaude.git\"\nTMP_DIR=\"\"\n\ncleanup() { [ -n \"${TMP_DIR:-}\" ] && rm -rf \"$TMP_DIR\"; }\ntrap cleanup EXIT\n\n# ---- Parse args ------------------------------------------------------------\nwhile [ $# -gt 0 ]; do\n case \"$1\" in\n --user) PREFIX=\"$HOME/.local/bin\" ;;\n --prefix) PREFIX=\"$2\"; shift ;;\n *) echo \"install.sh: unknown option: $1\" >&2; exit 1 ;;\n esac\n shift\ndone\n\n# ---- Resolve install directory ---------------------------------------------\nif [ -z \"$PREFIX\" ]; then\n if [ -w /usr/local/bin ]; then\n PREFIX=\"/usr/local/bin\"\n elif [ \"$(id -u)\" = \"0\" ]; then\n PREFIX=\"/usr/local/bin\"\n else\n echo \"install.sh: /usr/local/bin is not writable. Options:\"\n echo \" • Run with sudo: curl ... | sudo bash\"\n echo \" • User install: curl ... | bash -s -- --user\"\n exit 1\n fi\nfi\n\nmkdir -p \"$PREFIX\"\n\necho \"install.sh: installing to $PREFIX\"\n\n# ---- Get the scripts -------------------------------------------------------\nREPO_DIR=\"\"\n# If we're already inside a repo clone, use it directly.\nself_dir=\"$(cd \"$(dirname \"$0\")\" 2>/dev/null && pwd || true)\"\nif [ -n \"${self_dir:-}\" ] && [ -f \"$self_dir/dsclaude\" ] && [ -d \"$self_dir/.git\" ]; then\n REPO_DIR=\"$self_dir\"\n echo \"install.sh: using local repo at $REPO_DIR\"\nelse\n TMP_DIR=\"$(mktemp -d -t dsclaude-install.XXXXXX)\"\n echo \"install.sh: cloning $REPO_URL ...\"\n git clone --depth 1 \"$REPO_URL\" \"$TMP_DIR\" >/dev/null 2>&1 || {\n echo \"install.sh: git clone failed. Check your network or install git.\" >&2\n exit 1\n }\n REPO_DIR=\"$TMP_DIR\"\nfi\n\n# ---- Install CLI launchers (no extension) ----------------------------------\ncount=0\necho \"install.sh: installing CLI launchers...\"\nfor script in \"$REPO_DIR\"/*claude; do\n name=\"$(basename \"$script\")\"\n # Skip .ps1 files and desktop configurators.\n case \"$name\" in\n *.ps1|*-desktop) continue ;;\n esac\n # Skip non-files.\n [ ! -f \"$script\" ] && continue\n cp \"$script\" \"$PREFIX/$name\"\n chmod +x \"$PREFIX/$name\"\n echo \" $name\"\n count=$((count + 1))\ndone\n\n# ---- Install desktop configurators -----------------------------------------\necho \"install.sh: installing desktop configurators...\"\nfor script in \"$REPO_DIR\"/*-desktop; do\n name=\"$(basename \"$script\")\"\n [ ! -f \"$script\" ] && continue\n cp \"$script\" \"$PREFIX/$name\"\n chmod +x \"$PREFIX/$name\"\n echo \" $name\"\n count=$((count + 1))\ndone\n\necho \"\"\necho \"✓ Installed $count scripts to $PREFIX\"\n\n# ---- PATH reminder ----------------------------------------------------------\nif [ \"$PREFIX\" = \"$HOME/.local/bin\" ]; then\n if ! echo \"$PATH\" | tr ':' '\\n' | grep -qFx \"$PREFIX\"; then\n echo \"\"\n echo \"⚠️ $PREFIX is not in your PATH. Add this to your ~/.zshrc or ~/.bashrc:\"\n echo \" export PATH=\\\"\\$HOME/.local/bin:\\$PATH\\\"\"\n fi\nfi\n\necho \"\"\necho \"Now set an API key and run xclaude (auto-detect) or any launcher directly:\"\necho \" export DEEPSEEK_API_KEY=sk-...\"\necho \" xclaude\"\n"}}, "lib/common.sh": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785745937.3398902, "n": 5579, "h": "14341077f29081fc", "c": "#!/usr/bin/env bash\n# lib/common.sh — shared functions sourced by all *claude launcher scripts.\n# This file is not meant to be executed directly.\n#\n# Each launcher must set this variable before sourcing this file:\n# SELF_DIR — absolute path to the directory containing the launcher script\n#\n# Before calling export_anthropic_base the launcher must set:\n# BASE_URL, API_KEY, MAIN_MODEL, FLASH_MODEL\n\n# ---- find_repo: locate the xxclaude repository checkout -----------------\n# Usage: repo=\"$(find_repo \"DSCLAUDE_HOME\")\"\nfind_repo() {\n\tlocal home_var=\"$1\"\n\tif [ -d \"$SELF_DIR/.git\" ]; then\n\t\techo \"$SELF_DIR\"\n\t\treturn 0\n\tfi\n\tif [ -n \"${!home_var:-}\" ] && [ -d \"${!home_var}/.git\" ]; then\n\t\techo \"${!home_var}\"\n\t\treturn 0\n\tfi\n\tif [ -d \"$HOME/github/xxclaude/.git\" ]; then\n\t\techo \"$HOME/github/xxclaude\"\n\t\treturn 0\n\tfi\n\techo \"\"\n}\n\n# ---- do_update: git pull latest from the repo ---------------------------\n# Usage: do_update \"dsclaude\" \"DSCLAUDE_HOME\"\ndo_update() {\n\tlocal name=\"$1\" home_var=\"$2\"\n\tlocal repo\n\trepo=\"$(find_repo \"$home_var\")\"\n\tif [ -z \"$repo\" ]; then\n\t\techo \"$name: cannot find the xxclaude repo for self-update.\" >&2\n\t\techo \" Set $home_var=/path/to/xxclaude or cd into the repo and run ./$name update\" >&2\n\t\texit 1\n\tfi\n\techo \"$name: pulling latest from $repo ...\"\n\tgit -C \"$repo\" pull && echo \"$name: updated.\" || {\n\t\techo \"$name: git pull failed. Check network or resolve conflicts manually.\" >&2\n\t\texit 1\n\t}\n\texit 0\n}\n\n# ---- extract_key_from_file: get an API key value from a shell rc file ---\n# Skips commented-out lines (starting with # after optional whitespace).\n# Usage: key=\"$(extract_key_from_file \"$HOME/.zshrc\" \"DEEPSEEK_API_KEY\")\"\nextract_key_from_file() {\n\tlocal file=\"$1\" var=\"$2\"\n\t[ -f \"$file\" ] || return 1\n\tgrep -v '^[[:space:]]*#' \"$file\" |\n\t\tgrep -E \"^[[:space:]]*(export[[:space:]]+)?${var}=\" |\n\t\ttail -n1 |\n\t\tsed -E \"s/^[[:space:]]*(export[[:space:]]+)?${var}=//\" |\n\t\tsed -E 's/^\"(.*)\"$/\\1/; s/^'\"'\"'(.*)'\"'\"'$/\\1/'\n}\n\n# ---- resolve_api_key: env var first, then shell rc files ----------------\n# Usage: API_KEY=\"$(resolve_api_key \"DEEPSEEK_API_KEY\")\"\nresolve_api_key() {\n\tlocal var=\"$1\"\n\t# 1) Already in environment\n\tif [ -n \"${!var:-}\" ]; then\n\t\tprintf '%s' \"${!var}\"\n\t\treturn 0\n\tfi\n\t# 2) Shell rc files\n\tlocal f candidate\n\tfor f in \"$HOME/.zshrc\" \"$HOME/.bashrc\" \"$HOME/.bash_profile\" \"$HOME/.profile\"; do\n\t\tcandidate=\"$(extract_key_from_file \"$f\" \"$var\" || true)\"\n\t\tif [ -n \"${candidate:-}\" ]; then\n\t\t\tprintf '%s' \"$candidate\"\n\t\t\treturn 0\n\t\tfi\n\tdone\n\t# Return 0 even when not found: callers use API_KEY=\"$(resolve_api_key ...)\"\n\t# under `set -e`, and a nonzero status would kill the launcher silently\n\t# before its friendly \"key not found\" message can print.\n\treturn 0\n}\n\n# ---- export_anthropic_base: set the common ANTHROPIC_* env vars ---------\n# Caller must set BASE_URL, API_KEY, MAIN_MODEL, FLASH_MODEL first.\nexport_anthropic_base() {\n\t# Clear lingering official Anthropic credentials before launching,\n\t# otherwise they shadow ANTHROPIC_AUTH_TOKEN and traffic hits api.anthropic.com.\n\tunset ANTHROPIC_API_KEY 2>/dev/null || true\n\n\texport ANTHROPIC_BASE_URL=\"$BASE_URL\"\n\texport ANTHROPIC_AUTH_TOKEN=\"$API_KEY\"\n\texport ANTHROPIC_MODEL=\"$MAIN_MODEL\"\n\texport ANTHROPIC_DEFAULT_OPUS_MODEL=\"$MAIN_MODEL\"\n\texport ANTHROPIC_DEFAULT_SONNET_MODEL=\"$MAIN_MODEL\"\n\texport ANTHROPIC_DEFAULT_HAIKU_MODEL=\"$FLASH_MODEL\"\n\n\t# Prevent Claude Code from pinging api.anthropic.com for non-essential\n\t# features (billing check, feature flags) — those always fail on third-\n\t# party backends and produce noisy connection-error logs.\n\texport CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1\n}\n\n# ---- check_version: handle --version / -V flag -------------------------\n# Usage: check_version \"dsclaude\" \"$@\"\n# If the first arg is --version or -V, prints version info and exits.\ncheck_version() {\n\tlocal name=\"$1\"\n\tshift\n\tif [ $# -gt 0 ] && { [ \"$1\" = \"--version\" ] || [ \"$1\" = \"-V\" ]; }; then\n\t\tlocal repo ver=\"unknown\"\n\t\trepo=\"$(find_repo \"DUMMY\" 2>/dev/null || true)\"\n\t\t[ -n \"$repo\" ] && ver=\"$(git -C \"$repo\" describe --tags --always --dirty 2>/dev/null || echo \"unknown\")\"\n\t\techo \"$name $ver\"\n\t\texit 0\n\tfi\n}\n\n# ---- set_custom_model: expose alternate model in /model picker ----------\n# Usage: set_custom_model \"$OTHER_MODEL\" \"$MAIN_MODEL\" \"$OTHER_DESC\"\nset_custom_model() {\n\tlocal other=\"$1\" main=\"$2\" desc=\"$3\"\n\tif [ \"$other\" != \"$main\" ]; then\n\t\texport ANTHROPIC_CUSTOM_MODEL_OPTION=\"$other\"\n\t\texport ANTHROPIC_CUSTOM_MODEL_OPTION_NAME=\"$other\"\n\t\texport ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION=\"$desc\"\n\tfi\n}\n\n# ---- apply_context_and_effort: set CTX/output/effort env vars -----------\n# Caller must set CTX, OUTPUT_CAP, EFFORT, LONG_CTX before calling.\napply_context_and_effort() {\n\tif [ -n \"${EFFORT:-}\" ]; then export CLAUDE_CODE_EFFORT_LEVEL=\"$EFFORT\"; fi\n\n\tlocal ctx=\"${CTX:-}\"\n\tif [ -z \"$ctx\" ] && [ \"${LONG_CTX:-0}\" = \"1\" ]; then ctx=\"1048576\"; fi\n\tif [ -n \"$ctx\" ]; then\n\t\texport CLAUDE_CODE_MAX_CONTEXT_TOKENS=\"$ctx\"\n\t\texport DISABLE_COMPACT=1\n\tfi\n\n\tif [ -n \"${OUTPUT_CAP:-}\" ]; then export CLAUDE_CODE_MAX_OUTPUT_TOKENS=\"$OUTPUT_CAP\"; fi\n}\n\n# ---- show_banner_and_launch: print banner and exec claude ----------------\n# Usage: show_banner_and_launch \"DeepSeek\" \"$@\"\nshow_banner_and_launch() {\n\tlocal label=\"$1\"\n\tshift\n\tlocal banner=\"🚀 Claude Code on $label → $MAIN_MODEL ($BASE_URL)\"\n\t[ -n \"${CTX:-}\" ] && banner=\"$banner | ctx=$CTX\"\n\t[ -n \"${EFFORT:-}\" ] && banner=\"$banner | effort=$EFFORT\"\n\t[ \"${OTHER_MODEL:-}\" != \"$MAIN_MODEL\" ] && banner=\"$banner (switch mid-session via /model)\"\n\techo \"$banner\"\n\texec claude \"$@\"\n}\n"}, "c1f2e8a064922fce5be8b17bfba2cd0b5758cb64": {"t": 1785758056.2260745, "n": 5579, "h": "14341077f29081fc", "c": "#!/usr/bin/env bash\n# lib/common.sh — shared functions sourced by all *claude launcher scripts.\n# This file is not meant to be executed directly.\n#\n# Each launcher must set this variable before sourcing this file:\n# SELF_DIR — absolute path to the directory containing the launcher script\n#\n# Before calling export_anthropic_base the launcher must set:\n# BASE_URL, API_KEY, MAIN_MODEL, FLASH_MODEL\n\n# ---- find_repo: locate the xxclaude repository checkout -----------------\n# Usage: repo=\"$(find_repo \"DSCLAUDE_HOME\")\"\nfind_repo() {\n\tlocal home_var=\"$1\"\n\tif [ -d \"$SELF_DIR/.git\" ]; then\n\t\techo \"$SELF_DIR\"\n\t\treturn 0\n\tfi\n\tif [ -n \"${!home_var:-}\" ] && [ -d \"${!home_var}/.git\" ]; then\n\t\techo \"${!home_var}\"\n\t\treturn 0\n\tfi\n\tif [ -d \"$HOME/github/xxclaude/.git\" ]; then\n\t\techo \"$HOME/github/xxclaude\"\n\t\treturn 0\n\tfi\n\techo \"\"\n}\n\n# ---- do_update: git pull latest from the repo ---------------------------\n# Usage: do_update \"dsclaude\" \"DSCLAUDE_HOME\"\ndo_update() {\n\tlocal name=\"$1\" home_var=\"$2\"\n\tlocal repo\n\trepo=\"$(find_repo \"$home_var\")\"\n\tif [ -z \"$repo\" ]; then\n\t\techo \"$name: cannot find the xxclaude repo for self-update.\" >&2\n\t\techo \" Set $home_var=/path/to/xxclaude or cd into the repo and run ./$name update\" >&2\n\t\texit 1\n\tfi\n\techo \"$name: pulling latest from $repo ...\"\n\tgit -C \"$repo\" pull && echo \"$name: updated.\" || {\n\t\techo \"$name: git pull failed. Check network or resolve conflicts manually.\" >&2\n\t\texit 1\n\t}\n\texit 0\n}\n\n# ---- extract_key_from_file: get an API key value from a shell rc file ---\n# Skips commented-out lines (starting with # after optional whitespace).\n# Usage: key=\"$(extract_key_from_file \"$HOME/.zshrc\" \"DEEPSEEK_API_KEY\")\"\nextract_key_from_file() {\n\tlocal file=\"$1\" var=\"$2\"\n\t[ -f \"$file\" ] || return 1\n\tgrep -v '^[[:space:]]*#' \"$file\" |\n\t\tgrep -E \"^[[:space:]]*(export[[:space:]]+)?${var}=\" |\n\t\ttail -n1 |\n\t\tsed -E \"s/^[[:space:]]*(export[[:space:]]+)?${var}=//\" |\n\t\tsed -E 's/^\"(.*)\"$/\\1/; s/^'\"'\"'(.*)'\"'\"'$/\\1/'\n}\n\n# ---- resolve_api_key: env var first, then shell rc files ----------------\n# Usage: API_KEY=\"$(resolve_api_key \"DEEPSEEK_API_KEY\")\"\nresolve_api_key() {\n\tlocal var=\"$1\"\n\t# 1) Already in environment\n\tif [ -n \"${!var:-}\" ]; then\n\t\tprintf '%s' \"${!var}\"\n\t\treturn 0\n\tfi\n\t# 2) Shell rc files\n\tlocal f candidate\n\tfor f in \"$HOME/.zshrc\" \"$HOME/.bashrc\" \"$HOME/.bash_profile\" \"$HOME/.profile\"; do\n\t\tcandidate=\"$(extract_key_from_file \"$f\" \"$var\" || true)\"\n\t\tif [ -n \"${candidate:-}\" ]; then\n\t\t\tprintf '%s' \"$candidate\"\n\t\t\treturn 0\n\t\tfi\n\tdone\n\t# Return 0 even when not found: callers use API_KEY=\"$(resolve_api_key ...)\"\n\t# under `set -e`, and a nonzero status would kill the launcher silently\n\t# before its friendly \"key not found\" message can print.\n\treturn 0\n}\n\n# ---- export_anthropic_base: set the common ANTHROPIC_* env vars ---------\n# Caller must set BASE_URL, API_KEY, MAIN_MODEL, FLASH_MODEL first.\nexport_anthropic_base() {\n\t# Clear lingering official Anthropic credentials before launching,\n\t# otherwise they shadow ANTHROPIC_AUTH_TOKEN and traffic hits api.anthropic.com.\n\tunset ANTHROPIC_API_KEY 2>/dev/null || true\n\n\texport ANTHROPIC_BASE_URL=\"$BASE_URL\"\n\texport ANTHROPIC_AUTH_TOKEN=\"$API_KEY\"\n\texport ANTHROPIC_MODEL=\"$MAIN_MODEL\"\n\texport ANTHROPIC_DEFAULT_OPUS_MODEL=\"$MAIN_MODEL\"\n\texport ANTHROPIC_DEFAULT_SONNET_MODEL=\"$MAIN_MODEL\"\n\texport ANTHROPIC_DEFAULT_HAIKU_MODEL=\"$FLASH_MODEL\"\n\n\t# Prevent Claude Code from pinging api.anthropic.com for non-essential\n\t# features (billing check, feature flags) — those always fail on third-\n\t# party backends and produce noisy connection-error logs.\n\texport CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1\n}\n\n# ---- check_version: handle --version / -V flag -------------------------\n# Usage: check_version \"dsclaude\" \"$@\"\n# If the first arg is --version or -V, prints version info and exits.\ncheck_version() {\n\tlocal name=\"$1\"\n\tshift\n\tif [ $# -gt 0 ] && { [ \"$1\" = \"--version\" ] || [ \"$1\" = \"-V\" ]; }; then\n\t\tlocal repo ver=\"unknown\"\n\t\trepo=\"$(find_repo \"DUMMY\" 2>/dev/null || true)\"\n\t\t[ -n \"$repo\" ] && ver=\"$(git -C \"$repo\" describe --tags --always --dirty 2>/dev/null || echo \"unknown\")\"\n\t\techo \"$name $ver\"\n\t\texit 0\n\tfi\n}\n\n# ---- set_custom_model: expose alternate model in /model picker ----------\n# Usage: set_custom_model \"$OTHER_MODEL\" \"$MAIN_MODEL\" \"$OTHER_DESC\"\nset_custom_model() {\n\tlocal other=\"$1\" main=\"$2\" desc=\"$3\"\n\tif [ \"$other\" != \"$main\" ]; then\n\t\texport ANTHROPIC_CUSTOM_MODEL_OPTION=\"$other\"\n\t\texport ANTHROPIC_CUSTOM_MODEL_OPTION_NAME=\"$other\"\n\t\texport ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION=\"$desc\"\n\tfi\n}\n\n# ---- apply_context_and_effort: set CTX/output/effort env vars -----------\n# Caller must set CTX, OUTPUT_CAP, EFFORT, LONG_CTX before calling.\napply_context_and_effort() {\n\tif [ -n \"${EFFORT:-}\" ]; then export CLAUDE_CODE_EFFORT_LEVEL=\"$EFFORT\"; fi\n\n\tlocal ctx=\"${CTX:-}\"\n\tif [ -z \"$ctx\" ] && [ \"${LONG_CTX:-0}\" = \"1\" ]; then ctx=\"1048576\"; fi\n\tif [ -n \"$ctx\" ]; then\n\t\texport CLAUDE_CODE_MAX_CONTEXT_TOKENS=\"$ctx\"\n\t\texport DISABLE_COMPACT=1\n\tfi\n\n\tif [ -n \"${OUTPUT_CAP:-}\" ]; then export CLAUDE_CODE_MAX_OUTPUT_TOKENS=\"$OUTPUT_CAP\"; fi\n}\n\n# ---- show_banner_and_launch: print banner and exec claude ----------------\n# Usage: show_banner_and_launch \"DeepSeek\" \"$@\"\nshow_banner_and_launch() {\n\tlocal label=\"$1\"\n\tshift\n\tlocal banner=\"🚀 Claude Code on $label → $MAIN_MODEL ($BASE_URL)\"\n\t[ -n \"${CTX:-}\" ] && banner=\"$banner | ctx=$CTX\"\n\t[ -n \"${EFFORT:-}\" ] && banner=\"$banner | effort=$EFFORT\"\n\t[ \"${OTHER_MODEL:-}\" != \"$MAIN_MODEL\" ] && banner=\"$banner (switch mid-session via /model)\"\n\techo \"$banner\"\n\texec claude \"$@\"\n}\n"}, "6e7f604972cf57ad3d384559760f9c7467bc71b6": {"t": 1785758058.3288758, "n": 5671, "h": "a121509fcb8bb099", "c": "#!/usr/bin/env bash\n# lib/common.sh — shared functions sourced by all *claude launcher scripts.\n# This file is not meant to be executed directly.\n#\n# Each launcher must set this variable before sourcing this file:\n# SELF_DIR — absolute path to the directory containing the launcher script\n#\n# Before calling export_anthropic_base the launcher must set:\n# BASE_URL, API_KEY, MAIN_MODEL, FLASH_MODEL\n\n# ---- find_repo: locate the xxclaude repository checkout -----------------\n# Usage: repo=\"$(find_repo \"DSCLAUDE_HOME\")\"\nfind_repo() {\n local home_var=\"$1\"\n if [ -d \"$SELF_DIR/.git\" ]; then echo \"$SELF_DIR\"; return 0; fi\n if [ -n \"${!home_var:-}\" ] && [ -d \"${!home_var}/.git\" ]; then echo \"${!home_var}\"; return 0; fi\n if [ -d \"$HOME/github/xxclaude/.git\" ]; then echo \"$HOME/github/xxclaude\"; return 0; fi\n echo \"\"\n}\n\n# ---- do_update: git pull latest from the repo ---------------------------\n# Usage: do_update \"dsclaude\" \"DSCLAUDE_HOME\"\ndo_update() {\n local name=\"$1\" home_var=\"$2\"\n local repo\n repo=\"$(find_repo \"$home_var\")\"\n if [ -z \"$repo\" ]; then\n echo \"$name: cannot find the xxclaude repo for self-update.\" >&2\n echo \" Set $home_var=/path/to/xxclaude or cd into the repo and run ./$name update\" >&2\n exit 1\n fi\n echo \"$name: pulling latest from $repo ...\"\n git -C \"$repo\" pull && echo \"$name: updated.\" || {\n echo \"$name: git pull failed. Check network or resolve conflicts manually.\" >&2\n exit 1\n }\n exit 0\n}\n\n# ---- extract_key_from_file: get an API key value from a shell rc file ---\n# Skips commented-out lines (starting with # after optional whitespace).\n# Usage: key=\"$(extract_key_from_file \"$HOME/.zshrc\" \"DEEPSEEK_API_KEY\")\"\nextract_key_from_file() {\n local file=\"$1\" var=\"$2\"\n [ -f \"$file\" ] || return 1\n grep -v '^[[:space:]]*#' \"$file\" \\\n | grep -E \"^[[:space:]]*(export[[:space:]]+)?${var}=\" \\\n | tail -n1 \\\n | sed -E \"s/^[[:space:]]*(export[[:space:]]+)?${var}=//\" \\\n | sed -E 's/^\"(.*)\"$/\\1/; s/^'\"'\"'(.*)'\"'\"'$/\\1/'\n}\n\n# ---- resolve_api_key: env var first, then shell rc files ----------------\n# Usage: API_KEY=\"$(resolve_api_key \"DEEPSEEK_API_KEY\")\"\nresolve_api_key() {\n local var=\"$1\"\n # 1) Already in environment\n if [ -n \"${!var:-}\" ]; then printf '%s' \"${!var}\"; return 0; fi\n # 2) Shell rc files\n local f candidate\n for f in \"$HOME/.zshrc\" \"$HOME/.bashrc\" \"$HOME/.bash_profile\" \"$HOME/.profile\"; do\n candidate=\"$(extract_key_from_file \"$f\" \"$var\" || true)\"\n if [ -n \"${candidate:-}\" ]; then printf '%s' \"$candidate\"; return 0; fi\n done\n # Return 0 even when not found: callers use API_KEY=\"$(resolve_api_key ...)\"\n # under `set -e`, and a nonzero status would kill the launcher silently\n # before its friendly \"key not found\" message can print.\n return 0\n}\n\n# ---- export_anthropic_base: set the common ANTHROPIC_* env vars ---------\n# Caller must set BASE_URL, API_KEY, MAIN_MODEL, FLASH_MODEL first.\nexport_anthropic_base() {\n # Clear lingering official Anthropic credentials before launching,\n # otherwise they shadow ANTHROPIC_AUTH_TOKEN and traffic hits api.anthropic.com.\n unset ANTHROPIC_API_KEY 2>/dev/null || true\n\n export ANTHROPIC_BASE_URL=\"$BASE_URL\"\n export ANTHROPIC_AUTH_TOKEN=\"$API_KEY\"\n export ANTHROPIC_MODEL=\"$MAIN_MODEL\"\n export ANTHROPIC_DEFAULT_OPUS_MODEL=\"$MAIN_MODEL\"\n export ANTHROPIC_DEFAULT_SONNET_MODEL=\"$MAIN_MODEL\"\n export ANTHROPIC_DEFAULT_HAIKU_MODEL=\"$FLASH_MODEL\"\n\n # Prevent Claude Code from pinging api.anthropic.com for non-essential\n # features (billing check, feature flags) — those always fail on third-\n # party backends and produce noisy connection-error logs.\n export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1\n}\n\n# ---- check_version: handle --version / -V flag -------------------------\n# Usage: check_version \"dsclaude\" \"$@\"\n# If the first arg is --version or -V, prints version info and exits.\ncheck_version() {\n local name=\"$1\"; shift\n if [ $# -gt 0 ] && { [ \"$1\" = \"--version\" ] || [ \"$1\" = \"-V\" ]; }; then\n local repo ver=\"unknown\"\n repo=\"$(find_repo \"DUMMY\" 2>/dev/null || true)\"\n [ -n \"$repo\" ] && ver=\"$(git -C \"$repo\" describe --tags --always --dirty 2>/dev/null || echo \"unknown\")\"\n echo \"$name $ver\"\n exit 0\n fi\n}\n\n# ---- set_custom_model: expose alternate model in /model picker ----------\n# Usage: set_custom_model \"$OTHER_MODEL\" \"$MAIN_MODEL\" \"$OTHER_DESC\"\nset_custom_model() {\n local other=\"$1\" main=\"$2\" desc=\"$3\"\n if [ \"$other\" != \"$main\" ]; then\n export ANTHROPIC_CUSTOM_MODEL_OPTION=\"$other\"\n export ANTHROPIC_CUSTOM_MODEL_OPTION_NAME=\"$other\"\n export ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION=\"$desc\"\n fi\n}\n\n# ---- apply_context_and_effort: set CTX/output/effort env vars -----------\n# Caller must set CTX, OUTPUT_CAP, EFFORT, LONG_CTX before calling.\napply_context_and_effort() {\n if [ -n \"${EFFORT:-}\" ]; then export CLAUDE_CODE_EFFORT_LEVEL=\"$EFFORT\"; fi\n\n local ctx=\"${CTX:-}\"\n if [ -z \"$ctx\" ] && [ \"${LONG_CTX:-0}\" = \"1\" ]; then ctx=\"1048576\"; fi\n if [ -n \"$ctx\" ]; then\n export CLAUDE_CODE_MAX_CONTEXT_TOKENS=\"$ctx\"\n export DISABLE_COMPACT=1\n fi\n\n if [ -n \"${OUTPUT_CAP:-}\" ]; then export CLAUDE_CODE_MAX_OUTPUT_TOKENS=\"$OUTPUT_CAP\"; fi\n}\n\n# ---- show_banner_and_launch: print banner and exec claude ----------------\n# Usage: show_banner_and_launch \"DeepSeek\" \"$@\"\nshow_banner_and_launch() {\n local label=\"$1\"; shift\n local banner=\"🚀 Claude Code on $label → $MAIN_MODEL ($BASE_URL)\"\n [ -n \"${CTX:-}\" ] && banner=\"$banner | ctx=$CTX\"\n [ -n \"${EFFORT:-}\" ] && banner=\"$banner | effort=$EFFORT\"\n [ \"${OTHER_MODEL:-}\" != \"$MAIN_MODEL\" ] && banner=\"$banner (switch mid-session via /model)\"\n echo \"$banner\"\n exec claude \"$@\"\n}\n"}, "2525882659f2c26f4e2221ba062878ff8234b7c3": {"t": 1785758060.262947, "n": 5459, "h": "fe12d4d33d83aab2", "c": "#!/usr/bin/env bash\n# lib/common.sh — shared functions sourced by all *claude launcher scripts.\n# This file is not meant to be executed directly.\n#\n# Each launcher must set this variable before sourcing this file:\n# SELF_DIR — absolute path to the directory containing the launcher script\n#\n# Before calling export_anthropic_base the launcher must set:\n# BASE_URL, API_KEY, MAIN_MODEL, FLASH_MODEL\n\n# ---- find_repo: locate the xxclaude repository checkout -----------------\n# Usage: repo=\"$(find_repo \"DSCLAUDE_HOME\")\"\nfind_repo() {\n local home_var=\"$1\"\n if [ -d \"$SELF_DIR/.git\" ]; then echo \"$SELF_DIR\"; return 0; fi\n if [ -n \"${!home_var:-}\" ] && [ -d \"${!home_var}/.git\" ]; then echo \"${!home_var}\"; return 0; fi\n if [ -d \"$HOME/github/xxclaude/.git\" ]; then echo \"$HOME/github/xxclaude\"; return 0; fi\n echo \"\"\n}\n\n# ---- do_update: git pull latest from the repo ---------------------------\n# Usage: do_update \"dsclaude\" \"DSCLAUDE_HOME\"\ndo_update() {\n local name=\"$1\" home_var=\"$2\"\n local repo\n repo=\"$(find_repo \"$home_var\")\"\n if [ -z \"$repo\" ]; then\n echo \"$name: cannot find the xxclaude repo for self-update.\" >&2\n echo \" Set $home_var=/path/to/xxclaude or cd into the repo and run ./$name update\" >&2\n exit 1\n fi\n echo \"$name: pulling latest from $repo ...\"\n git -C \"$repo\" pull && echo \"$name: updated.\" || {\n echo \"$name: git pull failed. Check network or resolve conflicts manually.\" >&2\n exit 1\n }\n exit 0\n}\n\n# ---- extract_key_from_file: get an API key value from a shell rc file ---\n# Skips commented-out lines (starting with # after optional whitespace).\n# Usage: key=\"$(extract_key_from_file \"$HOME/.zshrc\" \"DEEPSEEK_API_KEY\")\"\nextract_key_from_file() {\n local file=\"$1\" var=\"$2\"\n [ -f \"$file\" ] || return 1\n grep -v '^[[:space:]]*#' \"$file\" \\\n | grep -E \"^[[:space:]]*(export[[:space:]]+)?${var}=\" \\\n | tail -n1 \\\n | sed -E \"s/^[[:space:]]*(export[[:space:]]+)?${var}=//\" \\\n | sed -E 's/^\"(.*)\"$/\\1/; s/^'\"'\"'(.*)'\"'\"'$/\\1/'\n}\n\n# ---- resolve_api_key: env var first, then shell rc files ----------------\n# Usage: API_KEY=\"$(resolve_api_key \"DEEPSEEK_API_KEY\")\"\nresolve_api_key() {\n local var=\"$1\"\n # 1) Already in environment\n if [ -n \"${!var:-}\" ]; then printf '%s' \"${!var}\"; return 0; fi\n # 2) Shell rc files\n local f candidate\n for f in \"$HOME/.zshrc\" \"$HOME/.bashrc\" \"$HOME/.bash_profile\" \"$HOME/.profile\"; do\n candidate=\"$(extract_key_from_file \"$f\" \"$var\" || true)\"\n if [ -n \"${candidate:-}\" ]; then printf '%s' \"$candidate\"; return 0; fi\n done\n return 1\n}\n\n# ---- export_anthropic_base: set the common ANTHROPIC_* env vars ---------\n# Caller must set BASE_URL, API_KEY, MAIN_MODEL, FLASH_MODEL first.\nexport_anthropic_base() {\n # Clear lingering official Anthropic credentials before launching,\n # otherwise they shadow ANTHROPIC_AUTH_TOKEN and traffic hits api.anthropic.com.\n unset ANTHROPIC_API_KEY 2>/dev/null || true\n\n export ANTHROPIC_BASE_URL=\"$BASE_URL\"\n export ANTHROPIC_AUTH_TOKEN=\"$API_KEY\"\n export ANTHROPIC_MODEL=\"$MAIN_MODEL\"\n export ANTHROPIC_DEFAULT_OPUS_MODEL=\"$MAIN_MODEL\"\n export ANTHROPIC_DEFAULT_SONNET_MODEL=\"$MAIN_MODEL\"\n export ANTHROPIC_DEFAULT_HAIKU_MODEL=\"$FLASH_MODEL\"\n\n # Prevent Claude Code from pinging api.anthropic.com for non-essential\n # features (billing check, feature flags) — those always fail on third-\n # party backends and produce noisy connection-error logs.\n export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1\n}\n\n# ---- check_version: handle --version / -V flag -------------------------\n# Usage: check_version \"dsclaude\" \"$@\"\n# If the first arg is --version or -V, prints version info and exits.\ncheck_version() {\n local name=\"$1\"; shift\n if [ $# -gt 0 ] && { [ \"$1\" = \"--version\" ] || [ \"$1\" = \"-V\" ]; }; then\n local repo ver=\"unknown\"\n repo=\"$(find_repo \"DUMMY\" 2>/dev/null || true)\"\n [ -n \"$repo\" ] && ver=\"$(git -C \"$repo\" describe --tags --always --dirty 2>/dev/null || echo \"unknown\")\"\n echo \"$name $ver\"\n exit 0\n fi\n}\n\n# ---- set_custom_model: expose alternate model in /model picker ----------\n# Usage: set_custom_model \"$OTHER_MODEL\" \"$MAIN_MODEL\" \"$OTHER_DESC\"\nset_custom_model() {\n local other=\"$1\" main=\"$2\" desc=\"$3\"\n if [ \"$other\" != \"$main\" ]; then\n export ANTHROPIC_CUSTOM_MODEL_OPTION=\"$other\"\n export ANTHROPIC_CUSTOM_MODEL_OPTION_NAME=\"$other\"\n export ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION=\"$desc\"\n fi\n}\n\n# ---- apply_context_and_effort: set CTX/output/effort env vars -----------\n# Caller must set CTX, OUTPUT_CAP, EFFORT, LONG_CTX before calling.\napply_context_and_effort() {\n if [ -n \"${EFFORT:-}\" ]; then export CLAUDE_CODE_EFFORT_LEVEL=\"$EFFORT\"; fi\n\n local ctx=\"${CTX:-}\"\n if [ -z \"$ctx\" ] && [ \"${LONG_CTX:-0}\" = \"1\" ]; then ctx=\"1048576\"; fi\n if [ -n \"$ctx\" ]; then\n export CLAUDE_CODE_MAX_CONTEXT_TOKENS=\"$ctx\"\n export DISABLE_COMPACT=1\n fi\n\n if [ -n \"${OUTPUT_CAP:-}\" ]; then export CLAUDE_CODE_MAX_OUTPUT_TOKENS=\"$OUTPUT_CAP\"; fi\n}\n\n# ---- show_banner_and_launch: print banner and exec claude ----------------\n# Usage: show_banner_and_launch \"DeepSeek\" \"$@\"\nshow_banner_and_launch() {\n local label=\"$1\"; shift\n local banner=\"🚀 Claude Code on $label → $MAIN_MODEL ($BASE_URL)\"\n [ -n \"${CTX:-}\" ] && banner=\"$banner | ctx=$CTX\"\n [ -n \"${EFFORT:-}\" ] && banner=\"$banner | effort=$EFFORT\"\n [ \"${OTHER_MODEL:-}\" != \"$MAIN_MODEL\" ] && banner=\"$banner (switch mid-session via /model)\"\n echo \"$banner\"\n exec claude \"$@\"\n}\n"}, "ea2a57d1593b741035a3e943052d52e07f75f119": {"t": 1785758061.8349183, "n": 4667, "h": "9ea278078e590e8b", "c": "#!/usr/bin/env bash\n# lib/common.sh — shared functions sourced by all *claude launcher scripts.\n# This file is not meant to be executed directly.\n#\n# Each launcher must set this variable before sourcing this file:\n# SELF_DIR — absolute path to the directory containing the launcher script\n#\n# Before calling export_anthropic_base the launcher must set:\n# BASE_URL, API_KEY, MAIN_MODEL, FLASH_MODEL\n\n# ---- find_repo: locate the xxclaude repository checkout -----------------\n# Usage: repo=\"$(find_repo \"DSCLAUDE_HOME\")\"\nfind_repo() {\n local home_var=\"$1\"\n if [ -d \"$SELF_DIR/.git\" ]; then echo \"$SELF_DIR\"; return 0; fi\n if [ -n \"${!home_var:-}\" ] && [ -d \"${!home_var}/.git\" ]; then echo \"${!home_var}\"; return 0; fi\n if [ -d \"$HOME/github/xxclaude/.git\" ]; then echo \"$HOME/github/xxclaude\"; return 0; fi\n echo \"\"\n}\n\n# ---- do_update: git pull latest from the repo ---------------------------\n# Usage: do_update \"dsclaude\" \"DSCLAUDE_HOME\"\ndo_update() {\n local name=\"$1\" home_var=\"$2\"\n local repo\n repo=\"$(find_repo \"$home_var\")\"\n if [ -z \"$repo\" ]; then\n echo \"$name: cannot find the xxclaude repo for self-update.\" >&2\n echo \" Set $home_var=/path/to/xxclaude or cd into the repo and run ./$name update\" >&2\n exit 1\n fi\n echo \"$name: pulling latest from $repo ...\"\n git -C \"$repo\" pull && echo \"$name: updated.\" || {\n echo \"$name: git pull failed. Check network or resolve conflicts manually.\" >&2\n exit 1\n }\n exit 0\n}\n\n# ---- extract_key_from_file: get an API key value from a shell rc file ---\n# Skips commented-out lines (starting with # after optional whitespace).\n# Usage: key=\"$(extract_key_from_file \"$HOME/.zshrc\" \"DEEPSEEK_API_KEY\")\"\nextract_key_from_file() {\n local file=\"$1\" var=\"$2\"\n [ -f \"$file\" ] || return 1\n grep -v '^[[:space:]]*#' \"$file\" \\\n | grep -E \"^[[:space:]]*(export[[:space:]]+)?${var}=\" \\\n | tail -n1 \\\n | sed -E \"s/^[[:space:]]*(export[[:space:]]+)?${var}=//\" \\\n | sed -E 's/^\"(.*)\"$/\\1/; s/^'\"'\"'(.*)'\"'\"'$/\\1/'\n}\n\n# ---- resolve_api_key: env var first, then shell rc files ----------------\n# Usage: API_KEY=\"$(resolve_api_key \"DEEPSEEK_API_KEY\")\"\nresolve_api_key() {\n local var=\"$1\"\n # 1) Already in environment\n if [ -n \"${!var:-}\" ]; then printf '%s' \"${!var}\"; return 0; fi\n # 2) Shell rc files\n local f candidate\n for f in \"$HOME/.zshrc\" \"$HOME/.bashrc\" \"$HOME/.bash_profile\" \"$HOME/.profile\"; do\n candidate=\"$(extract_key_from_file \"$f\" \"$var\" || true)\"\n if [ -n \"${candidate:-}\" ]; then printf '%s' \"$candidate\"; return 0; fi\n done\n return 1\n}\n\n# ---- export_anthropic_base: set the common ANTHROPIC_* env vars ---------\n# Caller must set BASE_URL, API_KEY, MAIN_MODEL, FLASH_MODEL first.\nexport_anthropic_base() {\n # Clear lingering official Anthropic credentials before launching,\n # otherwise they shadow ANTHROPIC_AUTH_TOKEN and traffic hits api.anthropic.com.\n unset ANTHROPIC_API_KEY 2>/dev/null || true\n\n export ANTHROPIC_BASE_URL=\"$BASE_URL\"\n export ANTHROPIC_AUTH_TOKEN=\"$API_KEY\"\n export ANTHROPIC_MODEL=\"$MAIN_MODEL\"\n export ANTHROPIC_DEFAULT_OPUS_MODEL=\"$MAIN_MODEL\"\n export ANTHROPIC_DEFAULT_SONNET_MODEL=\"$MAIN_MODEL\"\n export ANTHROPIC_DEFAULT_HAIKU_MODEL=\"$FLASH_MODEL\"\n}\n\n# ---- set_custom_model: expose alternate model in /model picker ----------\n# Usage: set_custom_model \"$OTHER_MODEL\" \"$MAIN_MODEL\" \"$OTHER_DESC\"\nset_custom_model() {\n local other=\"$1\" main=\"$2\" desc=\"$3\"\n if [ \"$other\" != \"$main\" ]; then\n export ANTHROPIC_CUSTOM_MODEL_OPTION=\"$other\"\n export ANTHROPIC_CUSTOM_MODEL_OPTION_NAME=\"$other\"\n export ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION=\"$desc\"\n fi\n}\n\n# ---- apply_context_and_effort: set CTX/output/effort env vars -----------\n# Caller must set CTX, OUTPUT_CAP, EFFORT, LONG_CTX before calling.\napply_context_and_effort() {\n if [ -n \"${EFFORT:-}\" ]; then export CLAUDE_CODE_EFFORT_LEVEL=\"$EFFORT\"; fi\n\n local ctx=\"${CTX:-}\"\n if [ -z \"$ctx\" ] && [ \"${LONG_CTX:-0}\" = \"1\" ]; then ctx=\"1048576\"; fi\n if [ -n \"$ctx\" ]; then\n export CLAUDE_CODE_MAX_CONTEXT_TOKENS=\"$ctx\"\n export DISABLE_COMPACT=1\n fi\n\n if [ -n \"${OUTPUT_CAP:-}\" ]; then export CLAUDE_CODE_MAX_OUTPUT_TOKENS=\"$OUTPUT_CAP\"; fi\n}\n\n# ---- show_banner_and_launch: print banner and exec claude ----------------\n# Usage: show_banner_and_launch \"DeepSeek\" \"$@\"\nshow_banner_and_launch() {\n local label=\"$1\"; shift\n local banner=\"🚀 Claude Code on $label → $MAIN_MODEL ($BASE_URL)\"\n [ -n \"${CTX:-}\" ] && banner=\"$banner | ctx=$CTX\"\n [ -n \"${EFFORT:-}\" ] && banner=\"$banner | effort=$EFFORT\"\n [ \"${OTHER_MODEL:-}\" != \"$MAIN_MODEL\" ] && banner=\"$banner (switch mid-session via /model)\"\n echo \"$banner\"\n exec claude \"$@\"\n}\n"}}, "codex-setup.sh": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785745938.6689203, "n": 7814, "h": "cf3c20fa9b70ca02", "c": "#!/usr/bin/env bash\n# codex-setup.sh — generate ~/.codex/config.toml with all your available backends.\n#\n# Detects which API keys you've set (env or shell rc), then writes a Codex\n# config.toml pre-filled with provider blocks for every backend you can use.\n# The first detected key becomes the default provider.\n#\n# Codex only speaks the OpenAI Responses API (Chat Completions support was\n# removed in early 2026). Providers are wired accordingly:\n# - Native Responses (direct): dashscope, ark, longcat, minimax\n# - Chat-only (via local adapter codex-adapter.mjs): deepseek, moonshot,\n# zhipu, tokenhub, siliconflow\n# For adapter-backed providers, start the adapter before running codex:\n# nohup node codex-adapter.mjs > ~/.codex/adapter.log 2>&1 &\n#\n# Usage:\n# ./codex-setup.sh # interactive: pick from detected keys\n# ./codex-setup.sh --dry-run # print the config, don't write it\n# ./codex-setup.sh --force deepseek # set deepseek as default\n\nset -euo pipefail\n\nDRY_RUN=0; FORCE=\"\"\nwhile [ $# -gt 0 ]; do\n case \"$1\" in\n --dry-run) DRY_RUN=1 ;; --force) FORCE=\"$2\"; shift ;;\n *) echo \"codex-setup.sh: unknown option: $1\" >&2; exit 1 ;;\n esac; shift\ndone\n\nget_key() {\n local var=\"$1\"\n if [ -n \"${!var:-}\" ]; then printf '%s' \"${!var}\"; return 0; fi\n local f candidate\n for f in \"$HOME/.zshrc\" \"$HOME/.bashrc\" \"$HOME/.bash_profile\" \"$HOME/.profile\"; do\n [ -f \"$f\" ] || continue\n candidate=\"$(grep -v '^[[:space:]]*#' \"$f\" 2>/dev/null|grep -E \"^[[:space:]]*(export[[:space:]]+)?${var}=\"|tail -1|sed -E \"s/^[[:space:]]*(export[[:space:]]+)?${var}=//\"|sed -E 's/^\"(.*)\"$/\\1/; s/^'\"'\"'(.*)'\"'\"'$/\\1/'||true)\"\n if [ -n \"${candidate:-}\" ]; then printf '%s' \"$candidate\"; return 0; fi\n done; return 1\n}\n\n# Adapter port for chat-only providers (codex-adapter.mjs).\nADAPTER_PORT=\"${CODEX_ADAPTER_PORT:-8317}\"\nSCRIPT_DIR=\"$(cd \"$(dirname \"$0\")\" && pwd)\"\n\n# Provider data: id label base_url key_var model need_noauth mode\n# mode: responses = provider natively supports the OpenAI Responses API\n# adapter = chat-only; routed through the local codex-adapter.mjs\n# Separated by | for easy parsing.\nPROVIDERS_DATA=(\n \"deepseek|DeepSeek|http://127.0.0.1:${ADAPTER_PORT}/deepseek/v1|DEEPSEEK_API_KEY|deepseek-v4-pro|no|adapter\"\n \"dashscope|Qwen (Bailian)|https://dashscope.aliyuncs.com/compatible-mode/v1|DASHSCOPE_API_KEY|qwen-plus|no|responses\"\n \"moonshot|Moonshot Kimi|http://127.0.0.1:${ADAPTER_PORT}/moonshot/v1|KIMI_API_KEY|kimi-k2.5|no|adapter\"\n \"zhipu|ZhipuAI GLM|http://127.0.0.1:${ADAPTER_PORT}/zhipu/v1|GLM_API_KEY|glm-5.2|yes|adapter\"\n \"ark|Volcengine Ark|https://ark.cn-beijing.volces.com/api/v3|ARK_API_KEY|doubao-seed-2.0-code|yes|responses\"\n \"longcat|Meituan LongCat|https://api.longcat.chat/openai/v1|LONGCAT_API_KEY|LongCat-2.0|yes|responses\"\n \"minimax|MiniMax|https://api.minimaxi.com/v1|MINIMAX_API_KEY|MiniMax-M3|yes|responses\"\n \"tokenhub|Tencent TokenHub|http://127.0.0.1:${ADAPTER_PORT}/tokenhub/v1|HY_API_KEY|hy3-preview|yes|adapter\"\n \"siliconflow|SiliconFlow|http://127.0.0.1:${ADAPTER_PORT}/siliconflow/v1|SF_API_KEY|deepseek-ai/DeepSeek-V4-PRO|yes|adapter\"\n)\n\n# Detect available providers.\navailable_ids=()\navailable_labels=()\nfor entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth pmode <<< \"$entry\"\n k=\"$(get_key \"$pkey\" || true)\"\n if [ -n \"${k:-}\" ]; then available_ids+=(\"$pid\"); available_labels+=(\"$plabel\"); fi\ndone\n\nif [ ${#available_ids[@]} -eq 0 ]; then\n echo \"codex-setup.sh: no known API keys found. Set one in your ~/.zshrc:\" >&2\n echo \" export DEEPSEEK_API_KEY=sk-...\" >&2\n echo \" export KIMI_API_KEY=sk-...\" >&2\n exit 1\nfi\n\n# Pick default.\nDEFAULT_ID=\"${available_ids[0]}\"; DEFAULT_LABEL=\"${available_labels[0]}\"\nif [ -n \"$FORCE\" ]; then\n found=0; for i in \"${!available_ids[@]}\"; do\n if [ \"${available_ids[$i]}\" = \"$FORCE\" ]; then DEFAULT_ID=\"$FORCE\"; DEFAULT_LABEL=\"${available_labels[$i]}\"; found=1; break; fi\n done\n if [ \"$found\" = \"0\" ]; then echo \"codex-setup.sh: provider '$FORCE' key not set.\" >&2; exit 1; fi\nelif [ ${#available_ids[@]} -gt 1 ] && [ ! -t 0 ]; then\n # Non-interactive with multiple keys — use first.\n :\nelif [ ${#available_ids[@]} -gt 1 ]; then\n echo \"Multiple API keys detected. Which default provider?\"\n for i in \"${!available_ids[@]}\"; do echo \" $((i+1))) ${available_labels[$i]}\"; done\n read -r -p \"Choice [1-${#available_ids[@]}] (default 1): \" choice\n idx=\"${choice:-1}\"\n if [ \"$idx\" -ge 1 ] 2>/dev/null && [ \"$idx\" -le \"${#available_ids[@]}\" ]; then\n DEFAULT_ID=\"${available_ids[$((idx-1))]}\"; DEFAULT_LABEL=\"${available_labels[$((idx-1))]}\"\n fi\nfi\n\n# Find default model.\nDEFAULT_MODEL=\"\"; for entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth pmode <<< \"$entry\"\n [ \"$pid\" = \"$DEFAULT_ID\" ] && { DEFAULT_MODEL=\"$pmodel\"; break; }\ndone\n\n# ---- Generate config.toml --------------------------------------------------\nCONFIG_PATH=\"$HOME/.codex/config.toml\"\n\ngenerate_toml() {\n echo \"# Generated by codex-setup.sh — $(date +%Y-%m-%d)\"\n echo \"# Re-run codex-setup.sh to refresh when you add new API keys.\"\n echo \"\"\n echo \"model = \\\"$DEFAULT_MODEL\\\"\"\n echo \"model_provider = \\\"$DEFAULT_ID\\\"\"\n echo \"\"\n\n for entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth pmode <<< \"$entry\"\n # Only include if available.\n found=0; for aid in \"${available_ids[@]}\"; do [ \"$aid\" = \"$pid\" ] && found=1; done\n [ \"$found\" = \"0\" ] && continue\n\n echo \"# ---- $plabel ----\"\n if [ \"$pmode\" = \"adapter\" ]; then\n echo \"# Chat-only upstream: routed through the local codex-adapter.mjs proxy.\"\n echo \"# Start it first: nohup node ${SCRIPT_DIR}/codex-adapter.mjs > ~/.codex/adapter.log 2>&1 &\"\n fi\n echo \"[model_providers.$pid]\"\n echo \"name = \\\"$plabel\\\"\"\n echo \"base_url = \\\"$purl\\\"\"\n echo \"env_key = \\\"$pkey\\\"\"\n echo \"wire_api = \\\"responses\\\"\"\n if [ \"$pnoauth\" = \"yes\" ]; then echo \"requires_openai_auth = false\"; fi\n echo \"\"\n done\n}\n\n# Modern Codex profiles live in separate files (~/.codex/<name>.config.toml);\n# the legacy [profiles.*] tables in config.toml are rejected by current Codex.\nwrite_profile_files() {\n for entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth pmode <<< \"$entry\"\n found=0; for aid in \"${available_ids[@]}\"; do [ \"$aid\" = \"$pid\" ] && found=1; done\n [ \"$found\" = \"0\" ] && continue\n printf 'model = \"%s\"\\nmodel_provider = \"%s\"\\n' \"$pmodel\" \"$pid\" > \"$HOME/.codex/$pid.config.toml\"\n done\n}\n\n# True if any available provider is adapter-backed.\nneeds_adapter() {\n for entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth pmode <<< \"$entry\"\n for aid in \"${available_ids[@]}\"; do\n [ \"$aid\" = \"$pid\" ] && [ \"$pmode\" = \"adapter\" ] && return 0\n done\n done\n return 1\n}\n\nif [ \"$DRY_RUN\" = \"1\" ]; then\n generate_toml\n echo \"# Dry run — no file written.\"\nelse\n mkdir -p \"$HOME/.codex\"\n if [ -f \"$CONFIG_PATH\" ]; then\n cp \"$CONFIG_PATH\" \"${CONFIG_PATH}.bak.$(date +%Y%m%d%H%M%S)\"\n echo \"Backed up existing config.\"\n fi\n generate_toml > \"$CONFIG_PATH\"\n write_profile_files\n echo \"✓ Wrote $CONFIG_PATH (default: $DEFAULT_LABEL)\"\n echo \"✓ Wrote profile files: $(for id in \"${available_ids[@]}\"; do printf '%s.config.toml ' \"$id\"; done)\"\n echo \"\"\n echo \"Quick-switch profiles:\"\n for id in \"${available_ids[@]}\"; do echo \" codex --profile $id\"; done\n if needs_adapter; then\n echo \"\"\n echo \"⚠ Some of your providers are chat-only and need the local adapter.\"\n echo \" Start it once (survives until reboot):\"\n echo \" nohup node ${SCRIPT_DIR}/codex-adapter.mjs > ~/.codex/adapter.log 2>&1 &\"\n echo \" Check: curl http://127.0.0.1:${ADAPTER_PORT}/health\"\n fi\nfi\n"}, "ea2a57d1593b741035a3e943052d52e07f75f119": {"t": 1785758056.1875136, "n": 7814, "h": "cf3c20fa9b70ca02", "c": "#!/usr/bin/env bash\n# codex-setup.sh — generate ~/.codex/config.toml with all your available backends.\n#\n# Detects which API keys you've set (env or shell rc), then writes a Codex\n# config.toml pre-filled with provider blocks for every backend you can use.\n# The first detected key becomes the default provider.\n#\n# Codex only speaks the OpenAI Responses API (Chat Completions support was\n# removed in early 2026). Providers are wired accordingly:\n# - Native Responses (direct): dashscope, ark, longcat, minimax\n# - Chat-only (via local adapter codex-adapter.mjs): deepseek, moonshot,\n# zhipu, tokenhub, siliconflow\n# For adapter-backed providers, start the adapter before running codex:\n# nohup node codex-adapter.mjs > ~/.codex/adapter.log 2>&1 &\n#\n# Usage:\n# ./codex-setup.sh # interactive: pick from detected keys\n# ./codex-setup.sh --dry-run # print the config, don't write it\n# ./codex-setup.sh --force deepseek # set deepseek as default\n\nset -euo pipefail\n\nDRY_RUN=0; FORCE=\"\"\nwhile [ $# -gt 0 ]; do\n case \"$1\" in\n --dry-run) DRY_RUN=1 ;; --force) FORCE=\"$2\"; shift ;;\n *) echo \"codex-setup.sh: unknown option: $1\" >&2; exit 1 ;;\n esac; shift\ndone\n\nget_key() {\n local var=\"$1\"\n if [ -n \"${!var:-}\" ]; then printf '%s' \"${!var}\"; return 0; fi\n local f candidate\n for f in \"$HOME/.zshrc\" \"$HOME/.bashrc\" \"$HOME/.bash_profile\" \"$HOME/.profile\"; do\n [ -f \"$f\" ] || continue\n candidate=\"$(grep -v '^[[:space:]]*#' \"$f\" 2>/dev/null|grep -E \"^[[:space:]]*(export[[:space:]]+)?${var}=\"|tail -1|sed -E \"s/^[[:space:]]*(export[[:space:]]+)?${var}=//\"|sed -E 's/^\"(.*)\"$/\\1/; s/^'\"'\"'(.*)'\"'\"'$/\\1/'||true)\"\n if [ -n \"${candidate:-}\" ]; then printf '%s' \"$candidate\"; return 0; fi\n done; return 1\n}\n\n# Adapter port for chat-only providers (codex-adapter.mjs).\nADAPTER_PORT=\"${CODEX_ADAPTER_PORT:-8317}\"\nSCRIPT_DIR=\"$(cd \"$(dirname \"$0\")\" && pwd)\"\n\n# Provider data: id label base_url key_var model need_noauth mode\n# mode: responses = provider natively supports the OpenAI Responses API\n# adapter = chat-only; routed through the local codex-adapter.mjs\n# Separated by | for easy parsing.\nPROVIDERS_DATA=(\n \"deepseek|DeepSeek|http://127.0.0.1:${ADAPTER_PORT}/deepseek/v1|DEEPSEEK_API_KEY|deepseek-v4-pro|no|adapter\"\n \"dashscope|Qwen (Bailian)|https://dashscope.aliyuncs.com/compatible-mode/v1|DASHSCOPE_API_KEY|qwen-plus|no|responses\"\n \"moonshot|Moonshot Kimi|http://127.0.0.1:${ADAPTER_PORT}/moonshot/v1|KIMI_API_KEY|kimi-k2.5|no|adapter\"\n \"zhipu|ZhipuAI GLM|http://127.0.0.1:${ADAPTER_PORT}/zhipu/v1|GLM_API_KEY|glm-5.2|yes|adapter\"\n \"ark|Volcengine Ark|https://ark.cn-beijing.volces.com/api/v3|ARK_API_KEY|doubao-seed-2.0-code|yes|responses\"\n \"longcat|Meituan LongCat|https://api.longcat.chat/openai/v1|LONGCAT_API_KEY|LongCat-2.0|yes|responses\"\n \"minimax|MiniMax|https://api.minimaxi.com/v1|MINIMAX_API_KEY|MiniMax-M3|yes|responses\"\n \"tokenhub|Tencent TokenHub|http://127.0.0.1:${ADAPTER_PORT}/tokenhub/v1|HY_API_KEY|hy3-preview|yes|adapter\"\n \"siliconflow|SiliconFlow|http://127.0.0.1:${ADAPTER_PORT}/siliconflow/v1|SF_API_KEY|deepseek-ai/DeepSeek-V4-PRO|yes|adapter\"\n)\n\n# Detect available providers.\navailable_ids=()\navailable_labels=()\nfor entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth pmode <<< \"$entry\"\n k=\"$(get_key \"$pkey\" || true)\"\n if [ -n \"${k:-}\" ]; then available_ids+=(\"$pid\"); available_labels+=(\"$plabel\"); fi\ndone\n\nif [ ${#available_ids[@]} -eq 0 ]; then\n echo \"codex-setup.sh: no known API keys found. Set one in your ~/.zshrc:\" >&2\n echo \" export DEEPSEEK_API_KEY=sk-...\" >&2\n echo \" export KIMI_API_KEY=sk-...\" >&2\n exit 1\nfi\n\n# Pick default.\nDEFAULT_ID=\"${available_ids[0]}\"; DEFAULT_LABEL=\"${available_labels[0]}\"\nif [ -n \"$FORCE\" ]; then\n found=0; for i in \"${!available_ids[@]}\"; do\n if [ \"${available_ids[$i]}\" = \"$FORCE\" ]; then DEFAULT_ID=\"$FORCE\"; DEFAULT_LABEL=\"${available_labels[$i]}\"; found=1; break; fi\n done\n if [ \"$found\" = \"0\" ]; then echo \"codex-setup.sh: provider '$FORCE' key not set.\" >&2; exit 1; fi\nelif [ ${#available_ids[@]} -gt 1 ] && [ ! -t 0 ]; then\n # Non-interactive with multiple keys — use first.\n :\nelif [ ${#available_ids[@]} -gt 1 ]; then\n echo \"Multiple API keys detected. Which default provider?\"\n for i in \"${!available_ids[@]}\"; do echo \" $((i+1))) ${available_labels[$i]}\"; done\n read -r -p \"Choice [1-${#available_ids[@]}] (default 1): \" choice\n idx=\"${choice:-1}\"\n if [ \"$idx\" -ge 1 ] 2>/dev/null && [ \"$idx\" -le \"${#available_ids[@]}\" ]; then\n DEFAULT_ID=\"${available_ids[$((idx-1))]}\"; DEFAULT_LABEL=\"${available_labels[$((idx-1))]}\"\n fi\nfi\n\n# Find default model.\nDEFAULT_MODEL=\"\"; for entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth pmode <<< \"$entry\"\n [ \"$pid\" = \"$DEFAULT_ID\" ] && { DEFAULT_MODEL=\"$pmodel\"; break; }\ndone\n\n# ---- Generate config.toml --------------------------------------------------\nCONFIG_PATH=\"$HOME/.codex/config.toml\"\n\ngenerate_toml() {\n echo \"# Generated by codex-setup.sh — $(date +%Y-%m-%d)\"\n echo \"# Re-run codex-setup.sh to refresh when you add new API keys.\"\n echo \"\"\n echo \"model = \\\"$DEFAULT_MODEL\\\"\"\n echo \"model_provider = \\\"$DEFAULT_ID\\\"\"\n echo \"\"\n\n for entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth pmode <<< \"$entry\"\n # Only include if available.\n found=0; for aid in \"${available_ids[@]}\"; do [ \"$aid\" = \"$pid\" ] && found=1; done\n [ \"$found\" = \"0\" ] && continue\n\n echo \"# ---- $plabel ----\"\n if [ \"$pmode\" = \"adapter\" ]; then\n echo \"# Chat-only upstream: routed through the local codex-adapter.mjs proxy.\"\n echo \"# Start it first: nohup node ${SCRIPT_DIR}/codex-adapter.mjs > ~/.codex/adapter.log 2>&1 &\"\n fi\n echo \"[model_providers.$pid]\"\n echo \"name = \\\"$plabel\\\"\"\n echo \"base_url = \\\"$purl\\\"\"\n echo \"env_key = \\\"$pkey\\\"\"\n echo \"wire_api = \\\"responses\\\"\"\n if [ \"$pnoauth\" = \"yes\" ]; then echo \"requires_openai_auth = false\"; fi\n echo \"\"\n done\n}\n\n# Modern Codex profiles live in separate files (~/.codex/<name>.config.toml);\n# the legacy [profiles.*] tables in config.toml are rejected by current Codex.\nwrite_profile_files() {\n for entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth pmode <<< \"$entry\"\n found=0; for aid in \"${available_ids[@]}\"; do [ \"$aid\" = \"$pid\" ] && found=1; done\n [ \"$found\" = \"0\" ] && continue\n printf 'model = \"%s\"\\nmodel_provider = \"%s\"\\n' \"$pmodel\" \"$pid\" > \"$HOME/.codex/$pid.config.toml\"\n done\n}\n\n# True if any available provider is adapter-backed.\nneeds_adapter() {\n for entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth pmode <<< \"$entry\"\n for aid in \"${available_ids[@]}\"; do\n [ \"$aid\" = \"$pid\" ] && [ \"$pmode\" = \"adapter\" ] && return 0\n done\n done\n return 1\n}\n\nif [ \"$DRY_RUN\" = \"1\" ]; then\n generate_toml\n echo \"# Dry run — no file written.\"\nelse\n mkdir -p \"$HOME/.codex\"\n if [ -f \"$CONFIG_PATH\" ]; then\n cp \"$CONFIG_PATH\" \"${CONFIG_PATH}.bak.$(date +%Y%m%d%H%M%S)\"\n echo \"Backed up existing config.\"\n fi\n generate_toml > \"$CONFIG_PATH\"\n write_profile_files\n echo \"✓ Wrote $CONFIG_PATH (default: $DEFAULT_LABEL)\"\n echo \"✓ Wrote profile files: $(for id in \"${available_ids[@]}\"; do printf '%s.config.toml ' \"$id\"; done)\"\n echo \"\"\n echo \"Quick-switch profiles:\"\n for id in \"${available_ids[@]}\"; do echo \" codex --profile $id\"; done\n if needs_adapter; then\n echo \"\"\n echo \"⚠ Some of your providers are chat-only and need the local adapter.\"\n echo \" Start it once (survives until reboot):\"\n echo \" nohup node ${SCRIPT_DIR}/codex-adapter.mjs > ~/.codex/adapter.log 2>&1 &\"\n echo \" Check: curl http://127.0.0.1:${ADAPTER_PORT}/health\"\n fi\nfi\n"}, "886c26a598a8e72ae1a38b4f2e3141cff9e5ba93": {"t": 1785758058.103616, "n": 7789, "h": "0e2d7705c044e507", "c": "#!/usr/bin/env bash\n# codex-setup.sh — generate ~/.codex/config.toml with all your available backends.\n#\n# Detects which API keys you've set (env or shell rc), then writes a Codex\n# config.toml pre-filled with provider blocks for every backend you can use.\n# The first detected key becomes the default provider.\n#\n# Codex only speaks the OpenAI Responses API (Chat Completions support was\n# removed in early 2026). Providers are wired accordingly:\n# - Native Responses (direct): dashscope, ark, longcat, minimax\n# - Chat-only (via local adapter codex-adapter.mjs): deepseek, moonshot,\n# zhipu, tokenhub, siliconflow\n# For adapter-backed providers, start the adapter before running codex:\n# nohup node codex-adapter.mjs > ~/.codex/adapter.log 2>&1 &\n#\n# Usage:\n# ./codex-setup.sh # interactive: pick from detected keys\n# ./codex-setup.sh --dry-run # print the config, don't write it\n# ./codex-setup.sh --force deepseek # set deepseek as default\n\nset -euo pipefail\n\nDRY_RUN=0; FORCE=\"\"\nwhile [ $# -gt 0 ]; do\n case \"$1\" in\n --dry-run) DRY_RUN=1 ;; --force) FORCE=\"$2\"; shift ;;\n *) echo \"codex-setup.sh: unknown option: $1\" >&2; exit 1 ;;\n esac; shift\ndone\n\nget_key() {\n local var=\"$1\"\n if [ -n \"${!var:-}\" ]; then printf '%s' \"${!var}\"; return 0; fi\n local f candidate\n for f in \"$HOME/.zshrc\" \"$HOME/.bashrc\" \"$HOME/.bash_profile\" \"$HOME/.profile\"; do\n [ -f \"$f\" ] || continue\n candidate=\"$(grep -E \"^[[:space:]]*(export[[:space:]]+)?${var}=\" \"$f\" 2>/dev/null|tail -1|sed -E \"s/^[[:space:]]*(export[[:space:]]+)?${var}=//\"|sed -E 's/^\"(.*)\"$/\\1/; s/^'\"'\"'(.*)'\"'\"'$/\\1/'||true)\"\n if [ -n \"${candidate:-}\" ]; then printf '%s' \"$candidate\"; return 0; fi\n done; return 1\n}\n\n# Adapter port for chat-only providers (codex-adapter.mjs).\nADAPTER_PORT=\"${CODEX_ADAPTER_PORT:-8317}\"\nSCRIPT_DIR=\"$(cd \"$(dirname \"$0\")\" && pwd)\"\n\n# Provider data: id label base_url key_var model need_noauth mode\n# mode: responses = provider natively supports the OpenAI Responses API\n# adapter = chat-only; routed through the local codex-adapter.mjs\n# Separated by | for easy parsing.\nPROVIDERS_DATA=(\n \"deepseek|DeepSeek|http://127.0.0.1:${ADAPTER_PORT}/deepseek/v1|DEEPSEEK_API_KEY|deepseek-v4-pro|no|adapter\"\n \"dashscope|Qwen (Bailian)|https://dashscope.aliyuncs.com/compatible-mode/v1|DASHSCOPE_API_KEY|qwen-plus|no|responses\"\n \"moonshot|Moonshot Kimi|http://127.0.0.1:${ADAPTER_PORT}/moonshot/v1|KIMI_API_KEY|kimi-k2.5|no|adapter\"\n \"zhipu|ZhipuAI GLM|http://127.0.0.1:${ADAPTER_PORT}/zhipu/v1|GLM_API_KEY|glm-5.2|yes|adapter\"\n \"ark|Volcengine Ark|https://ark.cn-beijing.volces.com/api/v3|ARK_API_KEY|doubao-seed-2.0-code|yes|responses\"\n \"longcat|Meituan LongCat|https://api.longcat.chat/openai/v1|LONGCAT_API_KEY|LongCat-2.0|yes|responses\"\n \"minimax|MiniMax|https://api.minimaxi.com/v1|MINIMAX_API_KEY|MiniMax-M3|yes|responses\"\n \"tokenhub|Tencent TokenHub|http://127.0.0.1:${ADAPTER_PORT}/tokenhub/v1|HY_API_KEY|hy3-preview|yes|adapter\"\n \"siliconflow|SiliconFlow|http://127.0.0.1:${ADAPTER_PORT}/siliconflow/v1|SF_API_KEY|deepseek-ai/DeepSeek-V4-PRO|yes|adapter\"\n)\n\n# Detect available providers.\navailable_ids=()\navailable_labels=()\nfor entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth pmode <<< \"$entry\"\n k=\"$(get_key \"$pkey\" || true)\"\n if [ -n \"${k:-}\" ]; then available_ids+=(\"$pid\"); available_labels+=(\"$plabel\"); fi\ndone\n\nif [ ${#available_ids[@]} -eq 0 ]; then\n echo \"codex-setup.sh: no known API keys found. Set one in your ~/.zshrc:\" >&2\n echo \" export DEEPSEEK_API_KEY=sk-...\" >&2\n echo \" export KIMI_API_KEY=sk-...\" >&2\n exit 1\nfi\n\n# Pick default.\nDEFAULT_ID=\"${available_ids[0]}\"; DEFAULT_LABEL=\"${available_labels[0]}\"\nif [ -n \"$FORCE\" ]; then\n found=0; for i in \"${!available_ids[@]}\"; do\n if [ \"${available_ids[$i]}\" = \"$FORCE\" ]; then DEFAULT_ID=\"$FORCE\"; DEFAULT_LABEL=\"${available_labels[$i]}\"; found=1; break; fi\n done\n if [ \"$found\" = \"0\" ]; then echo \"codex-setup.sh: provider '$FORCE' key not set.\" >&2; exit 1; fi\nelif [ ${#available_ids[@]} -gt 1 ] && [ ! -t 0 ]; then\n # Non-interactive with multiple keys — use first.\n :\nelif [ ${#available_ids[@]} -gt 1 ]; then\n echo \"Multiple API keys detected. Which default provider?\"\n for i in \"${!available_ids[@]}\"; do echo \" $((i+1))) ${available_labels[$i]}\"; done\n read -r -p \"Choice [1-${#available_ids[@]}] (default 1): \" choice\n idx=\"${choice:-1}\"\n if [ \"$idx\" -ge 1 ] 2>/dev/null && [ \"$idx\" -le \"${#available_ids[@]}\" ]; then\n DEFAULT_ID=\"${available_ids[$((idx-1))]}\"; DEFAULT_LABEL=\"${available_labels[$((idx-1))]}\"\n fi\nfi\n\n# Find default model.\nDEFAULT_MODEL=\"\"; for entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth pmode <<< \"$entry\"\n [ \"$pid\" = \"$DEFAULT_ID\" ] && { DEFAULT_MODEL=\"$pmodel\"; break; }\ndone\n\n# ---- Generate config.toml --------------------------------------------------\nCONFIG_PATH=\"$HOME/.codex/config.toml\"\n\ngenerate_toml() {\n echo \"# Generated by codex-setup.sh — $(date +%Y-%m-%d)\"\n echo \"# Re-run codex-setup.sh to refresh when you add new API keys.\"\n echo \"\"\n echo \"model = \\\"$DEFAULT_MODEL\\\"\"\n echo \"model_provider = \\\"$DEFAULT_ID\\\"\"\n echo \"\"\n\n for entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth pmode <<< \"$entry\"\n # Only include if available.\n found=0; for aid in \"${available_ids[@]}\"; do [ \"$aid\" = \"$pid\" ] && found=1; done\n [ \"$found\" = \"0\" ] && continue\n\n echo \"# ---- $plabel ----\"\n if [ \"$pmode\" = \"adapter\" ]; then\n echo \"# Chat-only upstream: routed through the local codex-adapter.mjs proxy.\"\n echo \"# Start it first: nohup node ${SCRIPT_DIR}/codex-adapter.mjs > ~/.codex/adapter.log 2>&1 &\"\n fi\n echo \"[model_providers.$pid]\"\n echo \"name = \\\"$plabel\\\"\"\n echo \"base_url = \\\"$purl\\\"\"\n echo \"env_key = \\\"$pkey\\\"\"\n echo \"wire_api = \\\"responses\\\"\"\n if [ \"$pnoauth\" = \"yes\" ]; then echo \"requires_openai_auth = false\"; fi\n echo \"\"\n done\n}\n\n# Modern Codex profiles live in separate files (~/.codex/<name>.config.toml);\n# the legacy [profiles.*] tables in config.toml are rejected by current Codex.\nwrite_profile_files() {\n for entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth pmode <<< \"$entry\"\n found=0; for aid in \"${available_ids[@]}\"; do [ \"$aid\" = \"$pid\" ] && found=1; done\n [ \"$found\" = \"0\" ] && continue\n printf 'model = \"%s\"\\nmodel_provider = \"%s\"\\n' \"$pmodel\" \"$pid\" > \"$HOME/.codex/$pid.config.toml\"\n done\n}\n\n# True if any available provider is adapter-backed.\nneeds_adapter() {\n for entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth pmode <<< \"$entry\"\n for aid in \"${available_ids[@]}\"; do\n [ \"$aid\" = \"$pid\" ] && [ \"$pmode\" = \"adapter\" ] && return 0\n done\n done\n return 1\n}\n\nif [ \"$DRY_RUN\" = \"1\" ]; then\n generate_toml\n echo \"# Dry run — no file written.\"\nelse\n mkdir -p \"$HOME/.codex\"\n if [ -f \"$CONFIG_PATH\" ]; then\n cp \"$CONFIG_PATH\" \"${CONFIG_PATH}.bak.$(date +%Y%m%d%H%M%S)\"\n echo \"Backed up existing config.\"\n fi\n generate_toml > \"$CONFIG_PATH\"\n write_profile_files\n echo \"✓ Wrote $CONFIG_PATH (default: $DEFAULT_LABEL)\"\n echo \"✓ Wrote profile files: $(for id in \"${available_ids[@]}\"; do printf '%s.config.toml ' \"$id\"; done)\"\n echo \"\"\n echo \"Quick-switch profiles:\"\n for id in \"${available_ids[@]}\"; do echo \" codex --profile $id\"; done\n if needs_adapter; then\n echo \"\"\n echo \"⚠ Some of your providers are chat-only and need the local adapter.\"\n echo \" Start it once (survives until reboot):\"\n echo \" nohup node ${SCRIPT_DIR}/codex-adapter.mjs > ~/.codex/adapter.log 2>&1 &\"\n echo \" Check: curl http://127.0.0.1:${ADAPTER_PORT}/health\"\n fi\nfi\n"}, "cb94935e63131305afbfe7fb1ed68f5fb4ec0045": {"t": 1785758059.8834555, "n": 5434, "h": "4769cdfaedc5bf10", "c": "#!/usr/bin/env bash\n# codex-setup.sh — generate ~/.codex/config.toml with all your available backends.\n#\n# Detects which API keys you've set (env or shell rc), then writes a Codex\n# config.toml pre-filled with provider blocks for every backend you can use.\n# The first detected key becomes the default provider.\n#\n# Usage:\n# ./codex-setup.sh # interactive: pick from detected keys\n# ./codex-setup.sh --dry-run # print the config, don't write it\n# ./codex-setup.sh --force deepseek # set deepseek as default\n\nset -euo pipefail\n\nDRY_RUN=0; FORCE=\"\"\nwhile [ $# -gt 0 ]; do\n case \"$1\" in\n --dry-run) DRY_RUN=1 ;; --force) FORCE=\"$2\"; shift ;;\n *) echo \"codex-setup.sh: unknown option: $1\" >&2; exit 1 ;;\n esac; shift\ndone\n\nget_key() {\n local var=\"$1\"\n if [ -n \"${!var:-}\" ]; then printf '%s' \"${!var}\"; return 0; fi\n local f candidate\n for f in \"$HOME/.zshrc\" \"$HOME/.bashrc\" \"$HOME/.bash_profile\" \"$HOME/.profile\"; do\n [ -f \"$f\" ] || continue\n candidate=\"$(grep -E \"^[[:space:]]*(export[[:space:]]+)?${var}=\" \"$f\" 2>/dev/null|tail -1|sed -E \"s/^[[:space:]]*(export[[:space:]]+)?${var}=//\"|sed -E 's/^\"(.*)\"$/\\1/; s/^'\"'\"'(.*)'\"'\"'$/\\1/'||true)\"\n if [ -n \"${candidate:-}\" ]; then printf '%s' \"$candidate\"; return 0; fi\n done; return 1\n}\n\n# Provider data: id label base_url key_var model need_noauth\n# Separated by | for easy parsing.\nPROVIDERS_DATA=(\n \"deepseek|DeepSeek|https://api.deepseek.com/v1|DEEPSEEK_API_KEY|deepseek-chat|no\"\n \"dashscope|Qwen (Bailian)|https://dashscope.aliyuncs.com/compatible-mode/v1|DASHSCOPE_API_KEY|qwen-plus|no\"\n \"moonshot|Moonshot Kimi|https://api.moonshot.cn/v1|KIMI_API_KEY|kimi-k2.5|no\"\n \"zhipu|ZhipuAI GLM|https://open.bigmodel.cn/api/paas/v4|GLM_API_KEY|glm-4-flash|yes\"\n \"ark|Volcengine Ark|https://ark.cn-beijing.volces.com/api/v3|ARK_API_KEY|doubao-seed-2.0-code|yes\"\n \"longcat|Meituan LongCat|https://api.longcat.chat/openai|LONGCAT_API_KEY|LongCat-2.0|yes\"\n \"minimax|MiniMax|https://api.minimaxi.com/v1|MINIMAX_API_KEY|MiniMax-M3|yes\"\n \"tokenhub|Tencent TokenHub|https://api.lkeap.cloud.tencent.com/v1|HY_API_KEY|hy3-preview|yes\"\n \"siliconflow|SiliconFlow|https://api.siliconflow.cn/v1|SF_API_KEY|deepseek-ai/DeepSeek-V4-PRO|yes\"\n)\n\n# Detect available providers.\navailable_ids=()\navailable_labels=()\nfor entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth <<< \"$entry\"\n k=\"$(get_key \"$pkey\" || true)\"\n if [ -n \"${k:-}\" ]; then available_ids+=(\"$pid\"); available_labels+=(\"$plabel\"); fi\ndone\n\nif [ ${#available_ids[@]} -eq 0 ]; then\n echo \"codex-setup.sh: no known API keys found. Set one in your ~/.zshrc:\" >&2\n echo \" export DEEPSEEK_API_KEY=sk-...\" >&2\n echo \" export KIMI_API_KEY=sk-...\" >&2\n exit 1\nfi\n\n# Pick default.\nDEFAULT_ID=\"${available_ids[0]}\"; DEFAULT_LABEL=\"${available_labels[0]}\"\nif [ -n \"$FORCE\" ]; then\n found=0; for i in \"${!available_ids[@]}\"; do\n if [ \"${available_ids[$i]}\" = \"$FORCE\" ]; then DEFAULT_ID=\"$FORCE\"; DEFAULT_LABEL=\"${available_labels[$i]}\"; found=1; break; fi\n done\n if [ \"$found\" = \"0\" ]; then echo \"codex-setup.sh: provider '$FORCE' key not set.\" >&2; exit 1; fi\nelif [ ${#available_ids[@]} -gt 1 ] && [ ! -t 0 ]; then\n # Non-interactive with multiple keys — use first.\n :\nelif [ ${#available_ids[@]} -gt 1 ]; then\n echo \"Multiple API keys detected. Which default provider?\"\n for i in \"${!available_ids[@]}\"; do echo \" $((i+1))) ${available_labels[$i]}\"; done\n read -r -p \"Choice [1-${#available_ids[@]}] (default 1): \" choice\n idx=\"${choice:-1}\"\n if [ \"$idx\" -ge 1 ] 2>/dev/null && [ \"$idx\" -le \"${#available_ids[@]}\" ]; then\n DEFAULT_ID=\"${available_ids[$((idx-1))]}\"; DEFAULT_LABEL=\"${available_labels[$((idx-1))]}\"\n fi\nfi\n\n# Find default model.\nDEFAULT_MODEL=\"\"; for entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth <<< \"$entry\"\n [ \"$pid\" = \"$DEFAULT_ID\" ] && { DEFAULT_MODEL=\"$pmodel\"; break; }\ndone\n\n# ---- Generate config.toml --------------------------------------------------\nCONFIG_PATH=\"$HOME/.codex/config.toml\"\n\ngenerate_toml() {\n echo \"# Generated by codex-setup.sh — $(date +%Y-%m-%d)\"\n echo \"# Re-run codex-setup.sh to refresh when you add new API keys.\"\n echo \"\"\n echo \"model = \\\"$DEFAULT_MODEL\\\"\"\n echo \"model_provider = \\\"$DEFAULT_ID\\\"\"\n echo \"\"\n\n for entry in \"${PROVIDERS_DATA[@]}\"; do\n IFS='|' read -r pid plabel purl pkey pmodel pnoauth <<< \"$entry\"\n # Only include if available.\n found=0; for aid in \"${available_ids[@]}\"; do [ \"$aid\" = \"$pid\" ] && found=1; done\n [ \"$found\" = \"0\" ] && continue\n\n echo \"# ---- $plabel ----\"\n echo \"[model_providers.$pid]\"\n echo \"name = \\\"$plabel\\\"\"\n echo \"base_url = \\\"$purl\\\"\"\n echo \"env_key = \\\"$pkey\\\"\"\n echo \"wire_api = \\\"chat\\\"\"\n if [ \"$pnoauth\" = \"yes\" ]; then echo \"requires_openai_auth = false\"; fi\n echo \"\"\n echo \"[profiles.$pid]\"\n echo \"model_provider = \\\"$pid\\\"\"\n echo \"model = \\\"$pmodel\\\"\"\n echo \"\"\n done\n}\n\nif [ \"$DRY_RUN\" = \"1\" ]; then\n generate_toml\n echo \"# Dry run — no file written.\"\nelse\n mkdir -p \"$HOME/.codex\"\n if [ -f \"$CONFIG_PATH\" ]; then\n cp \"$CONFIG_PATH\" \"${CONFIG_PATH}.bak.$(date +%Y%m%d%H%M%S)\"\n echo \"Backed up existing config.\"\n fi\n generate_toml > \"$CONFIG_PATH\"\n echo \"✓ Wrote $CONFIG_PATH (default: $DEFAULT_LABEL)\"\n echo \"\"\n echo \"Quick-switch profiles:\"\n for id in \"${available_ids[@]}\"; do echo \" codex --profile $id\"; done\nfi\n"}}, "hyclaude": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785809840.6835127, "n": 5124, "h": "0dc509f92e74911a", "c": "#!/usr/bin/env bash\n# shellcheck disable=SC2034 # variables consumed by lib/common.sh\n# hyclaude — launch Claude Code on Tencent TokenHub's Anthropic-compatible API.\n#\n# Tencent TokenHub is a multi-model aggregator — one subscription gives access\n# to Hunyuan (HY3), DeepSeek, GLM, Kimi, MiniMax, Qwen, and more.\n#\n# Endpoint:\n# - Token Plan (recommended): https://api.lkeap.cloud.tencent.com/plan/anthropic\n# - Coding Plan: https://api.lkeap.cloud.tencent.com/coding/anthropic\n#\n# Reads HY_API_KEY from the environment first, then falls back to\n# ~/.zshrc / ~/.bashrc / ~/.bash_profile / ~/.profile if not already exported.\n#\n# Quick start (no install needed):\n# chmod +x hyclaude\n# ./hyclaude\n#\n# Optional — make it globally available:\n# sudo mv hyclaude /usr/local/bin/ && sudo chmod +x /usr/local/bin/hyclaude\n#\n# Use:\n# hyclaude # hy3-preview (Tencent default)\n# hyclaude fast # hy-mt2-lite (cheap / fast)\n# hyclaude deepseek # deepseek-v4-pro\n# hyclaude kimi # kimi-k2.7-code\n# hyclaude glm # glm-5.2\n# hyclaude minimax # minimax-m3\n# hyclaude qwen # qwen3.5-plus\n# hyclaude long # request max context window\n# hyclaude effort max # set reasoning effort (low|medium|high|xhigh|max)\n# hyclaude update # git pull latest from this repo\n# hyclaude --help # any remaining flag is forwarded to claude\n#\n# Optional env overrides:\n# HY_MODEL=hy3-preview # main model (any model on TokenHub)\n# HY_FLASH_MODEL=hy-mt2-lite # flash / haiku / subagent tier\n# HY_BASE_URL=https://.../anthropic # custom Anthropic-compatible base URL\n# HY_CTX=1048576 # max context tokens\n# HY_OUTPUT=8000 # cap output tokens\n# HY_EFFORT=max # CLAUDE_CODE_EFFORT_LEVEL\n#\n# Get your API key: https://cloud.tencent.com/product/lkeap\n\nset -euo pipefail\n\n# Resolve symlink to find the real script directory.\n_SELF=\"$0\"\nif [ -L \"$_SELF\" ]; then\n _LINK=\"$(readlink \"$_SELF\")\"\n case \"$_LINK\" in\n /*) _SELF=\"$_LINK\" ;;\n *) _SELF=\"$(cd \"$(dirname \"$_SELF\")\" && pwd)/$_LINK\" ;;\n esac\nfi\nSELF_DIR=\"$(cd \"$(dirname \"$_SELF\")\" && pwd)\"\nif [ -f \"$SELF_DIR/lib/common.sh\" ]; then source \"$SELF_DIR/lib/common.sh\"\nelif [ -f \"$SELF_DIR/../lib/common.sh\" ]; then source \"$SELF_DIR/../lib/common.sh\"\nelse echo \"hyclaude: cannot find lib/common.sh. Reinstall or cd to repo.\" >&2; exit 1; fi\n\ncheck_version \"hyclaude\" \"$@\"\n\nPRO_MODEL=\"${HY_MODEL:-hy3-preview}\"\nFLASH_MODEL=\"${HY_FLASH_MODEL:-hy-mt2-lite}\"\n\nif [ $# -gt 0 ] && [ \"$1\" = \"update\" ]; then\n do_update \"hyclaude\" \"HYCLAUDE_HOME\"\nfi\n\nAPI_KEY=\"$(resolve_api_key \"HY_API_KEY\")\"\nif [ -z \"$API_KEY\" ]; then\n echo \"❌ HY_API_KEY not found.\" >&2\n echo \" Add one line to ~/.zshrc or ~/.bashrc: export HY_API_KEY=your_api_key\" >&2\n echo \" Get your key at: https://cloud.tencent.com/product/lkeap\" >&2\n exit 1\nfi\n\nBASE_URL=\"${HY_BASE_URL:-https://api.lkeap.cloud.tencent.com/plan/anthropic}\"\n\nLONG_CTX=0\nEFFORT=\"${HY_EFFORT:-}\"\n\nMAIN_MODEL=\"\"\nwhile [ $# -gt 0 ]; do\n case \"$1\" in\n # Tier aliases\n max|pro|code) MAIN_MODEL=\"$PRO_MODEL\"; shift ;;\n fast|flash|lite) MAIN_MODEL=\"$FLASH_MODEL\"; shift ;;\n # Provider aliases\n kimi) MAIN_MODEL=\"kimi-k2.7-code\"; shift ;;\n kimi-pro|kimi-k2) MAIN_MODEL=\"kimi-k2.6\"; shift ;;\n deepseek) MAIN_MODEL=\"deepseek-v4-pro\"; shift ;;\n deepseek-flash) MAIN_MODEL=\"deepseek-v4-flash\"; shift ;;\n glm) MAIN_MODEL=\"glm-5.2\"; shift ;;\n minimax) MAIN_MODEL=\"minimax-m3\"; shift ;;\n qwen) MAIN_MODEL=\"qwen3.5-plus\"; shift ;;\n # Context & effort\n long) LONG_CTX=1; shift ;;\n effort)\n case \"${2:-}\" in\n low|medium|high|xhigh|max) EFFORT=\"$2\"; shift 2 ;;\n *) echo \"hyclaude: invalid effort level '${2:-}'. Use: low medium high xhigh max\" >&2; exit 1 ;;\n esac\n ;;\n --) shift; break ;;\n *) break ;;\n esac\ndone\n\nif [ -z \"$MAIN_MODEL\" ]; then MAIN_MODEL=\"$PRO_MODEL\"; fi\n\n# Pick a smart alternate for the /model picker.\ncase \"$MAIN_MODEL\" in\n \"$PRO_MODEL\") OTHER_MODEL=\"$FLASH_MODEL\"; OTHER_DESC=\"HY MT2 Lite — fast / cheap tier\" ;;\n \"$FLASH_MODEL\") OTHER_MODEL=\"$PRO_MODEL\"; OTHER_DESC=\"HY3 Preview — Tencent flagship\" ;;\n kimi-k2.7-code) OTHER_MODEL=\"kimi-k2.6\"; OTHER_DESC=\"Kimi K2.6 — full reasoning\" ;;\n kimi-k2.6) OTHER_MODEL=\"kimi-k2.7-code\"; OTHER_DESC=\"Kimi K2.7 Code — code specialist\" ;;\n deepseek-v4-pro) OTHER_MODEL=\"deepseek-v4-flash\"; OTHER_DESC=\"DeepSeek V4 Flash\" ;;\n deepseek-v4-flash) OTHER_MODEL=\"deepseek-v4-pro\"; OTHER_DESC=\"DeepSeek V4 Pro\" ;;\n *) OTHER_MODEL=\"$PRO_MODEL\"; OTHER_DESC=\"HY3 Preview — Tencent flagship\" ;;\nesac\n\nexport_anthropic_base\nexport CLAUDE_CODE_SUBAGENT_MODEL=\"$FLASH_MODEL\"\nset_custom_model \"$OTHER_MODEL\" \"$MAIN_MODEL\" \"$OTHER_DESC\"\n\nCTX=\"${HY_CTX:-}\"\nOUTPUT_CAP=\"${HY_OUTPUT:-}\"\napply_context_and_effort\n\nshow_banner_and_launch \"TokenHub\" \"$@\"\n"}}, "hyclaude.ps1": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785809841.2305827, "n": 6800, "h": "b9bc4931150b2a82", "c": "#!/usr/bin/env pwsh\n# hyclaude.ps1 — launch Claude Code on Tencent TokenHub's Anthropic-compatible API (Windows port).\n#\n# Tencent TokenHub aggregates Hunyuan, DeepSeek, GLM, Kimi, MiniMax, Qwen.\n# One subscription, one endpoint, many models.\n#\n# Endpoint: https://api.lkeap.cloud.tencent.com/plan/anthropic\n# Reads HY_API_KEY from process env first, then User/Machine env vars.\n#\n# Use:\n# pwsh -File ./hyclaude.ps1 # hy3-preview (Tencent default)\n# pwsh -File ./hyclaude.ps1 fast # hy-mt2-lite\n# pwsh -File ./hyclaude.ps1 kimi # kimi-k2.7-code\n# pwsh -File ./hyclaude.ps1 deepseek # deepseek-v4-pro\n# pwsh -File ./hyclaude.ps1 glm # glm-5.2\n# pwsh -File ./hyclaude.ps1 minimax # minimax-m3\n# pwsh -File ./hyclaude.ps1 qwen # qwen3.5-plus\n# pwsh -File ./hyclaude.ps1 long # max context window\n# pwsh -File ./hyclaude.ps1 effort max # set effort (low|medium|high|xhigh|max)\n# pwsh -File ./hyclaude.ps1 update # git pull\n#\n# Optional env overrides:\n# $env:HY_MODEL = 'hy3-preview' # main model\n# $env:HY_FLASH_MODEL = 'hy-mt2-lite' # flash tier\n# $env:HY_BASE_URL = 'https://.../anthropic' # custom base URL\n# $env:HY_CTX = '1048576' # max context tokens\n# $env:HY_OUTPUT = '8000' # cap output tokens\n# $env:HY_EFFORT = 'max' # CLAUDE_CODE_EFFORT_LEVEL\n\n[CmdletBinding()]\nparam(\n [Parameter(ValueFromRemainingArguments = $true)]\n [string[]]$Rest\n)\n\n$ErrorActionPreference = 'Stop'\n\nif ($PSVersionTable.PSVersion.Major -lt 7) {\n Write-Error @\"\nhyclaude.ps1: PowerShell 7+ required (you're on $($PSVersionTable.PSVersion)).\nInstall once: winget install Microsoft.PowerShell\nThen: pwsh -File .\\hyclaude.ps1\n\"@\n exit 1\n}\n\nfunction Invoke-HyclaudeUpdate {\n $repo = $null; $selfDir = Split-Path -Parent $PSCommandPath\n if (Test-Path (Join-Path $selfDir '.git')) { $repo = $selfDir }\n if (-not $repo -and $env:HYCLAUDE_HOME) { $repo = $env:HYCLAUDE_HOME }\n if (-not $repo) { $c = Join-Path $env:USERPROFILE 'github\\xxclaude'; if (Test-Path (Join-Path $c '.git')) { $repo = $c } }\n if (-not $repo) { Write-Error \"hyclaude: cannot find xxclaude repo.\"; exit 1 }\n Write-Host \"hyclaude: pulling latest from $repo ...\"\n git -C $repo pull; if ($LASTEXITCODE -ne 0) { Write-Error 'hyclaude: git pull failed.'; exit 1 }\n Write-Host 'hyclaude: updated.'; exit 0\n}\n\nfunction Resolve-ApiKey {\n if ($env:HY_API_KEY) { return $env:HY_API_KEY }\n foreach ($scope in 'User','Machine') { $v=[Environment]::GetEnvironmentVariable('HY_API_KEY',$scope); if($v){return $v} }\n Write-Error \"HY_API_KEY not found.`n setx HY_API_KEY `\"your_api_key`\"`n Get your key: https://cloud.tencent.com/product/lkeap\"; exit 1\n}\n\n$mainModel = $null; $LongCtx = $false; $Effort = if($env:HY_EFFORT){$env:HY_EFFORT}else{''}\n$remaining = @(); $rest = @($Rest); $i = 0\n:argloop while ($i -lt $rest.Count) {\n $a = $rest[$i]\n switch -CaseSensitive ($a) {\n 'update' { Invoke-HyclaudeUpdate }\n 'max' { $i++; break }; 'pro' { $i++; break }; 'code' { $i++; break }\n 'fast' { $mainModel = 'hy-mt2-lite'; $i++; break }\n 'flash' { $mainModel = 'hy-mt2-lite'; $i++; break }\n 'lite' { $mainModel = 'hy-mt2-lite'; $i++; break }\n 'kimi' { $mainModel = 'kimi-k2.7-code'; $i++; break }\n 'kimi-pro' { $mainModel = 'kimi-k2.6'; $i++; break }\n 'kimi-k2' { $mainModel = 'kimi-k2.6'; $i++; break }\n 'deepseek' { $mainModel = 'deepseek-v4-pro'; $i++; break }\n 'deepseek-flash'{ $mainModel = 'deepseek-v4-flash'; $i++; break }\n 'glm' { $mainModel = 'glm-5.2'; $i++; break }\n 'minimax' { $mainModel = 'minimax-m3'; $i++; break }\n 'qwen' { $mainModel = 'qwen3.5-plus'; $i++; break }\n 'long' { $LongCtx=$true; $i++; break }\n 'effort' { $i++; if($i -lt $rest.Count){$l=$rest[$i];if($l -in 'low','medium','high','xhigh','max'){$Effort=$l;$i++;break}else{Write-Error \"hyclaude: invalid effort level '$l'. Use: low medium high xhigh max\";exit 1}}else{Write-Error \"hyclaude: 'effort' requires a level\";exit 1} }\n '--' { $i++; if($i -lt $rest.Count){$remaining+=$rest[$i..($rest.Count-1)]}; break argloop }\n default { $remaining+=$rest[$i..($rest.Count-1)]; break argloop }\n }\n}\n\n$apiKey = Resolve-ApiKey\n$baseUrl = if($env:HY_BASE_URL) {$env:HY_BASE_URL} else{'https://api.lkeap.cloud.tencent.com/plan/anthropic'}\n$proModel = if($env:HY_MODEL) {$env:HY_MODEL} else{'hy3-preview'}\n$flashModel = if($env:HY_FLASH_MODEL){$env:HY_FLASH_MODEL} else{'hy-mt2-lite'}\nif(-not $mainModel){$mainModel=$proModel}\n\nswitch -Wildcard ($mainModel) {\n $proModel { $otherModel=$flashModel; $otherDesc='HY MT2 Lite — fast / cheap tier' }\n $flashModel { $otherModel=$proModel; $otherDesc='HY3 Preview — Tencent flagship' }\n 'kimi-k2.7-code' { $otherModel='kimi-k2.6'; $otherDesc='Kimi K2.6' }\n 'kimi-k2.6' { $otherModel='kimi-k2.7-code'; $otherDesc='Kimi K2.7 Code' }\n 'deepseek-v4-pro' { $otherModel='deepseek-v4-flash'; $otherDesc='DeepSeek V4 Flash' }\n 'deepseek-v4-flash'{ $otherModel='deepseek-v4-pro'; $otherDesc='DeepSeek V4 Pro' }\n default { $otherModel=$proModel; $otherDesc='HY3 Preview' }\n}\n\n$env:ANTHROPIC_API_KEY=$null\n$env:ANTHROPIC_BASE_URL=$baseUrl; $env:ANTHROPIC_AUTH_TOKEN=$apiKey\n$env:ANTHROPIC_MODEL=$mainModel; $env:ANTHROPIC_DEFAULT_OPUS_MODEL=$mainModel; $env:ANTHROPIC_DEFAULT_SONNET_MODEL=$mainModel\n$env:ANTHROPIC_DEFAULT_HAIKU_MODEL=$flashModel; $env:CLAUDE_CODE_SUBAGENT_MODEL=$flashModel\n$env:CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC='1'\nif($otherModel -ne $mainModel){\n $env:ANTHROPIC_CUSTOM_MODEL_OPTION=$otherModel; $env:ANTHROPIC_CUSTOM_MODEL_OPTION_NAME=$otherModel\n $env:ANTHROPIC_CUSTOM_MODEL_OPTION_DESCRIPTION=$otherDesc\n}\nif($Effort){$env:CLAUDE_CODE_EFFORT_LEVEL=$Effort}\n$ctx=if($env:HY_CTX){$env:HY_CTX}elseif($LongCtx){'1048576'}else{''}\nif($ctx){$env:CLAUDE_CODE_MAX_CONTEXT_TOKENS=$ctx;$env:DISABLE_COMPACT='1'}\nif($env:HY_OUTPUT){$env:CLAUDE_CODE_MAX_OUTPUT_TOKENS=$env:HY_OUTPUT}\n\nif(-not(Get-Command claude -ErrorAction SilentlyContinue)){Write-Error \"hyclaude: `claude` CLI not found.`n Install: npm install -g @anthropic-ai/claude-code\";exit 1}\n\n$banner=\"🚀 Claude Code on TokenHub → $mainModel ($baseUrl)\"\nif($ctx){$banner+=\" | ctx=$ctx\"}; if($Effort){$banner+=\" | effort=$Effort\"}\nif($otherModel -ne $mainModel){$banner+=' (switch mid-session via /model)'}\nWrite-Host $banner; & claude @remaining; exit $LASTEXITCODE\n"}}, "hyclaude-desktop": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785809841.2772586, "n": 5655, "h": "ea690797839ee745", "c": "#!/usr/bin/env bash\n# hyclaude-desktop — configure Claude Desktop to use Tencent TokenHub as inference backend.\n#\n# Edits ~/Library/Application Support/Claude-3p/configLibrary/{_meta,<uuid>}.json\n# and restarts Claude Desktop. macOS only.\n#\n# Usage:\n# hyclaude-desktop # configure to HY3 Preview and restart\n# hyclaude-desktop kimi # use kimi-k2.7-code\n# hyclaude-desktop deepseek # use deepseek-v4-pro\n# hyclaude-desktop glm # use glm-5.2\n# hyclaude-desktop minimax # use minimax-m3\n# hyclaude-desktop qwen # use qwen3.5-plus\n# hyclaude-desktop update # git pull\n# hyclaude-desktop -h # help\n#\n# Reads HY_API_KEY from env or ~/.zshrc & friends (else prompts).\n# Base URL: https://api.lkeap.cloud.tencent.com/plan/anthropic\n\nset -euo pipefail\n\nCONFIG_DIR=\"$HOME/Library/Application Support/Claude-3p/configLibrary\"\nMETA=\"$CONFIG_DIR/_meta.json\"\nENTRY_NAME=\"hyclaude-desktop\"\nAUTH_SCHEME=\"bearer\"\nMAIN_MODEL=\"hy3-preview\"\nFAST_MODEL=\"hy-mt2-lite\"\n\nwhile [[ $# -gt 0 ]]; do\n case \"$1\" in\n -h|--help) sed -n '2,17p' \"$0\" | sed 's/^# \\{0,1\\}//'; exit 0 ;;\n update) SELF_DIR=\"$(cd \"$(dirname \"$0\")\" && pwd)\"\n echo \"hyclaude-desktop: pulling latest from $SELF_DIR ...\"\n git -C \"$SELF_DIR\" pull && echo \"hyclaude-desktop: updated.\" || { echo \"git pull failed.\" >&2; exit 1; }; exit 0 ;;\n max|pro|code) MAIN_MODEL=\"hy3-preview\"; FAST_MODEL=\"hy-mt2-lite\"; shift ;;\n fast|flash|lite) MAIN_MODEL=\"hy-mt2-lite\"; FAST_MODEL=\"hy-mt2-lite\"; shift ;;\n kimi) MAIN_MODEL=\"kimi-k2.7-code\"; FAST_MODEL=\"hy-mt2-lite\"; shift ;;\n kimi-pro|kimi-k2) MAIN_MODEL=\"kimi-k2.6\"; FAST_MODEL=\"kimi-k2.6\"; shift ;;\n deepseek) MAIN_MODEL=\"deepseek-v4-pro\"; FAST_MODEL=\"deepseek-v4-flash\"; shift ;;\n deepseek-flash) MAIN_MODEL=\"deepseek-v4-flash\"; FAST_MODEL=\"deepseek-v4-flash\"; shift ;;\n glm) MAIN_MODEL=\"glm-5.2\"; FAST_MODEL=\"glm-5.2\"; shift ;;\n minimax) MAIN_MODEL=\"minimax-m3\"; FAST_MODEL=\"minimax-m3\"; shift ;;\n qwen) MAIN_MODEL=\"qwen3.5-plus\"; FAST_MODEL=\"qwen3.5-plus\"; shift ;;\n *) echo \"hyclaude-desktop: unknown argument: $1\" >&2; exit 2 ;;\n esac\ndone\n\npreflight() {\n [[ \"$(uname)\" == \"Darwin\" ]] || { echo \"macOS only.\" >&2; exit 1; }\n [[ -d \"/Applications/Claude.app\" ]] || { echo \"Claude.app not found.\" >&2; exit 1; }\n [[ -x \"/usr/bin/jq\" ]] || { echo \"jq not found.\" >&2; exit 1; }\n local ds=\"$HOME/Library/Application Support/Claude/developer_settings.json\"\n if [[ ! -f \"$ds\" ]] || ! /usr/bin/jq -e '.allowDevTools==true' \"$ds\" >/dev/null 2>&1; then\n echo \"hyclaude-desktop: Enable Developer Mode first (Help → Troubleshooting → Enable Developer Mode)\" >&2; exit 1\n fi\n}\n\nresolve_api_key() {\n if [[ -n \"${HY_API_KEY:-}\" ]]; then printf '%s' \"$HY_API_KEY\"; return 0; fi\n local rc found=\"\"\n for rc in \"$HOME/.zshrc\" \"$HOME/.bashrc\" \"$HOME/.bash_profile\" \"$HOME/.profile\"; do\n [[ -r \"$rc\" ]] || continue\n found=\"$(grep -v '^[[:space:]]*#' \"$rc\" 2>/dev/null|grep -E '^[[:space:]]*export[[:space:]]+HY_API_KEY='|tail -1|sed -E 's/^[^=]*=//; s/^\"(.*)\"$/\\1/; s/^'\\''(.*)'\\''$/\\1/'||true)\"\n if [[ -n \"$found\" ]]; then printf '%s' \"$found\"; return 0; fi\n done\n local key\n key=\"$(osascript 2>/dev/null <<'APPLESCRIPT'||true\ntry;set theKey to text returned of (display dialog \"HY API Key not found.\\nPaste your Tencent TokenHub API Key:\" default answer \"\" with hidden answer with title \"hyclaude-desktop\");return theKey;end try\nAPPLESCRIPT\n)\"\n if [[ -z \"$key\" ]]; then echo \"hyclaude-desktop: no API Key provided. Aborting.\" >&2; exit 1; fi\n printf '%s' \"$key\"\n}\n\nconfirm_or_abort() { echo; echo \"About to: $1\"; echo \"Press Enter to continue, Ctrl-C to abort.\"; read -r _; }\n\nwrite_entry() {\n local uuid=\"$1\"; local entry_path=\"$CONFIG_DIR/${uuid}.json\"; local tmp=\"${entry_path}.tmp\"\n local content\n content=\"$(jq -n --arg baseUrl \"$BASE_URL\" --arg apiKey \"$HY_KEY\" --arg auth \"$AUTH_SCHEME\" --arg main \"$MAIN_MODEL\" --arg fast \"$FAST_MODEL\" \\\n '{inferenceProvider:\"gateway\",inferenceGatewayBaseUrl:$baseUrl,inferenceGatewayApiKey:$apiKey,inferenceGatewayAuthScheme:$auth,unstableDisableModelVerification:true,inferenceModels:([{name:$main,supports1m:false}]+(if $fast!=$main then[{name:$fast,supports1m:false}]else[]end))}')\"\n printf '%s' \"$content\" > \"$tmp\"; chmod 600 \"$tmp\"; mv \"$tmp\" \"$entry_path\"\n}\n\nensure_meta_entry() {\n mkdir -p \"$CONFIG_DIR\"\n local existing_uuid=\"\"\n if [[ -f \"$META\" ]]; then existing_uuid=\"$(jq -r --arg name \"$ENTRY_NAME\" '.entries[]?|select(.name==$name)|.id' \"$META\" 2>/dev/null|head -1)\"; fi\n local uuid; if [[ -n \"$existing_uuid\" ]]; then uuid=\"$existing_uuid\"; else uuid=\"$(uuidgen | tr 'A-Z' 'a-z')\"; fi\n local tmp=\"${META}.tmp\" content\n if [[ -f \"$META\" ]]; then\n content=\"$(jq --arg id \"$uuid\" --arg name \"$ENTRY_NAME\" '.appliedId=$id|.entries=((.entries//[])|map(select(.name!=$name))+[{id:$id,name:$name}])' \"$META\")\"\n else content=\"$(jq -n --arg id \"$uuid\" --arg name \"$ENTRY_NAME\" '{appliedId:$id,entries:[{id:$id,name:$name}]}')\"; fi\n printf '%s' \"$content\" > \"$tmp\"; chmod 600 \"$tmp\"; mv \"$tmp\" \"$META\"; printf '%s' \"$uuid\"\n}\n\nrestart_claude() { killall Claude 2>/dev/null || true; sleep 1; open -a Claude; }\n\nBASE_URL=\"${HY_BASE_URL:-https://api.lkeap.cloud.tencent.com/plan/anthropic}\"\npreflight; HY_KEY=\"$(resolve_api_key)\"\nconfirm_or_abort \"configure Claude Desktop to use Tencent TokenHub ($BASE_URL, $MAIN_MODEL) and restart.\"\nUUID=\"$(ensure_meta_entry)\"; write_entry \"$UUID\"; restart_claude\n\ncat <<'EOF'\n\nDone. Claude Desktop is restarting with Tencent TokenHub as the inference backend.\nRe-run hyclaude-desktop any time to refresh the gateway config.\nEOF\n"}}, "codex-adapter.mjs": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785809845.4331455, "n": 18425, "h": "64d9d0c18ce50c81", "c": "#!/usr/bin/env node\n// codex-adapter.mjs — local OpenAI Responses→Chat Completions translation proxy.\n//\n// Codex CLI only speaks the OpenAI Responses API, but several providers\n// (DeepSeek, Kimi, Zhipu GLM, Tencent TokenHub, SiliconFlow) only expose\n// Chat Completions. This adapter sits between them:\n//\n// Codex --Responses--> http://127.0.0.1:8317/<provider>/v1/responses\n// --Chat------> https://<upstream>/chat/completions\n//\n// Zero dependencies; requires Node 18+ (global fetch). The Authorization\n// header from Codex is forwarded upstream as-is, so keys stay in Codex's\n// env_key mechanism and never touch this file.\n//\n// Usage:\n// node codex-adapter.mjs # listen on 127.0.0.1:8317\n// node codex-adapter.mjs --port 9000\n// CODEX_ADAPTER_PORT=9000 node codex-adapter.mjs\n//\n// Run in background:\n// nohup node codex-adapter.mjs > ~/.codex/adapter.log 2>&1 &\n//\n// Health check:\n// curl http://127.0.0.1:8317/health\n//\n// Notes:\n// - Reasoning output (reasoning_content) is streamed back to Codex as\n// reasoning summary deltas, so thinking is visible and the stream stays\n// alive during long thinking phases.\n// - `reasoning.effort` from Codex is dropped (providers differ on the\n// parameter; models default to their own thinking behavior).\n\nimport http from 'node:http';\n\nconst PORT = (() => {\n const i = process.argv.indexOf('--port');\n if (i !== -1 && process.argv[i + 1]) return Number(process.argv[i + 1]);\n return Number(process.env.CODEX_ADAPTER_PORT || 8317);\n})();\n\nconst MAX_BODY_SIZE = 10 * 1024 * 1024; // 10 MB\nconst UPSTREAM_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes\n\n// Chat-only upstreams. Override any URL with ADAPTER_<ID>_URL (uppercased id).\nconst UPSTREAMS = {\n deepseek: 'https://api.deepseek.com/chat/completions',\n moonshot: 'https://api.moonshot.cn/v1/chat/completions',\n zhipu: 'https://open.bigmodel.cn/api/paas/v4/chat/completions',\n tokenhub: 'https://api.lkeap.cloud.tencent.com/v1/chat/completions',\n siliconflow: 'https://api.siliconflow.cn/v1/chat/completions',\n};\nfor (const id of Object.keys(UPSTREAMS)) {\n const env = process.env[`ADAPTER_${id.toUpperCase()}_URL`];\n if (env) UPSTREAMS[id] = env;\n}\n\n// ---- Request translation: Responses body -> Chat body ----------------------\n\nfunction toChatBody(body) {\n const messages = [];\n if (body.instructions) messages.push({ role: 'system', content: body.instructions });\n\n const items = typeof body.input === 'string'\n ? [{ type: 'message', role: 'user', content: body.input }]\n : Array.isArray(body.input) ? body.input : [];\n\n for (const item of items) {\n const type = item.type || 'message';\n if (type === 'message') {\n const role = item.role === 'developer' ? 'system' : item.role;\n const content = typeof item.content === 'string'\n ? item.content\n : (item.content || []).map(p => p.text || '').join('');\n messages.push({ role, content });\n } else if (type === 'function_call') {\n const call = {\n id: item.call_id || item.id,\n type: 'function',\n function: { name: item.name, arguments: item.arguments || '' },\n };\n const last = messages[messages.length - 1];\n // Merge consecutive tool calls into one assistant turn (parallel calls).\n if (last && last.role === 'assistant' && last.tool_calls) last.tool_calls.push(call);\n else messages.push({ role: 'assistant', content: null, tool_calls: [call] });\n } else if (type === 'function_call_output') {\n const out = typeof item.output === 'string' ? item.output : JSON.stringify(item.output);\n messages.push({ role: 'tool', tool_call_id: item.call_id, content: out });\n }\n // reasoning / item_reference / other item types: nothing to send upstream.\n }\n\n const chat = { model: body.model, messages };\n\n if (Array.isArray(body.tools)) {\n const fns = body.tools.filter(t => t.type === 'function');\n if (fns.length) {\n chat.tools = fns.map(t => ({\n type: 'function',\n function: { name: t.name, description: t.description, parameters: t.parameters },\n }));\n }\n }\n if (body.tool_choice && body.tool_choice !== 'auto') chat.tool_choice = body.tool_choice;\n if (typeof body.parallel_tool_calls === 'boolean') chat.parallel_tool_calls = body.parallel_tool_calls;\n if (body.temperature != null) chat.temperature = body.temperature;\n if (body.top_p != null) chat.top_p = body.top_p;\n if (body.max_output_tokens != null) chat.max_tokens = body.max_output_tokens;\n if (body.text?.format?.type === 'json_schema') {\n chat.response_format = {\n type: 'json_schema',\n json_schema: {\n name: body.text.format.name,\n schema: body.text.format.schema,\n strict: body.text.format.strict,\n },\n };\n }\n if (body.stream) {\n chat.stream = true;\n chat.stream_options = { include_usage: true };\n }\n return chat;\n}\n\n// ---- Response translation helpers ------------------------------------------\n\nfunction mapUsage(u) {\n if (!u) return null;\n return {\n input_tokens: u.prompt_tokens || 0,\n input_tokens_details: { cached_tokens: u.prompt_tokens_details?.cached_tokens || 0 },\n output_tokens: u.completion_tokens || 0,\n output_tokens_details: { reasoning_tokens: u.completion_tokens_details?.reasoning_tokens || 0 },\n total_tokens: u.total_tokens || 0,\n };\n}\n\nlet respCounter = 0;\n\nfunction buildOutput(msg) {\n const output = [];\n let n = 0;\n if (msg.reasoning_content) {\n output.push({\n type: 'reasoning', id: `rs_${++n}`,\n summary: [{ type: 'summary_text', text: msg.reasoning_content }], content: [],\n });\n }\n if (msg.content) {\n output.push({\n type: 'message', id: `msg_${++n}`, status: 'completed', role: 'assistant',\n content: [{ type: 'output_text', annotations: [], text: msg.content }],\n });\n }\n for (const tc of msg.tool_calls || []) {\n output.push({\n type: 'function_call', id: `fc_${++n}`, status: 'completed',\n call_id: tc.id, name: tc.function?.name, arguments: tc.function?.arguments || '',\n });\n }\n return output;\n}\n\nfunction toResponseObject(chatResp) {\n const choice = chatResp.choices?.[0] || {};\n const msg = choice.message || {};\n const incomplete = choice.finish_reason === 'length';\n return {\n id: `resp_${chatResp.id || ++respCounter}`,\n object: 'response',\n created_at: chatResp.created || Math.floor(Date.now() / 1000),\n status: incomplete ? 'incomplete' : 'completed',\n incomplete_details: incomplete ? { reason: 'max_output_tokens' } : null,\n error: null,\n model: chatResp.model,\n output: buildOutput(msg),\n usage: mapUsage(chatResp.usage),\n };\n}\n\n// ---- Streaming: Chat SSE -> Responses SSE -----------------------------------\n\n// Tracks the currently-open output item and emits properly ordered\n// Responses events as chat deltas arrive.\nclass StreamTranslator {\n constructor(write) {\n this.write = write;\n this.seq = 0;\n this.outputIndex = -1;\n this.current = null; // 'reasoning' | 'message' | 'function_call'\n this.itemId = null;\n this.text = '';\n this.reasoning = '';\n this.calls = new Map(); // upstream tool_call index -> {itemId, callId, name, args, outputIndex}\n this.output = []; // completed items, for response.completed\n this.usage = null;\n this.model = '';\n this.respId = `resp_${Date.now().toString(36)}${(++respCounter).toString(36)}`;\n this.created = Math.floor(Date.now() / 1000);\n this.started = false;\n }\n\n emit(type, extra) {\n this.write(`event: ${type}\\ndata: ${JSON.stringify({ type, sequence_number: this.seq++, ...extra })}\\n\\n`);\n }\n\n snapshot(status, final = false) {\n return {\n id: this.respId, object: 'response', created_at: this.created, status,\n error: null, incomplete_details: null, model: this.model,\n output: final ? this.output : [],\n usage: final ? this.usage : null,\n };\n }\n\n start(model) {\n if (this.started) return;\n this.started = true;\n this.model = model || '';\n this.emit('response.created', { response: this.snapshot('in_progress') });\n this.emit('response.in_progress', { response: this.snapshot('in_progress') });\n }\n\n closeCurrent() {\n if (this.current === 'reasoning') {\n const item = {\n type: 'reasoning', id: this.itemId,\n summary: [{ type: 'summary_text', text: this.reasoning }], content: [],\n };\n this.emit('response.reasoning_summary_text.done', {\n item_id: this.itemId, output_index: this.outputIndex, summary_index: 0, text: this.reasoning,\n });\n this.emit('response.reasoning_summary_part.done', {\n item_id: this.itemId, output_index: this.outputIndex, summary_index: 0,\n part: { type: 'summary_text', text: this.reasoning },\n });\n this.emit('response.output_item.done', { output_index: this.outputIndex, item });\n this.output.push(item);\n this.reasoning = '';\n } else if (this.current === 'message') {\n const item = {\n type: 'message', id: this.itemId, status: 'completed', role: 'assistant',\n content: [{ type: 'output_text', annotations: [], text: this.text }],\n };\n this.emit('response.output_text.done', {\n item_id: this.itemId, output_index: this.outputIndex, content_index: 0, text: this.text,\n });\n this.emit('response.content_part.done', {\n item_id: this.itemId, output_index: this.outputIndex, content_index: 0,\n part: { type: 'output_text', annotations: [], text: this.text },\n });\n this.emit('response.output_item.done', { output_index: this.outputIndex, item });\n this.output.push(item);\n this.text = '';\n }\n this.current = null;\n }\n\n openItem(kind) {\n if (this.current === kind) return;\n this.closeCurrent();\n this.current = kind;\n this.outputIndex++;\n if (kind === 'reasoning') {\n this.itemId = `rs_${this.outputIndex}`;\n this.emit('response.output_item.added', {\n output_index: this.outputIndex,\n item: { type: 'reasoning', id: this.itemId, summary: [], content: [] },\n });\n this.emit('response.reasoning_summary_part.added', {\n item_id: this.itemId, output_index: this.outputIndex, summary_index: 0,\n part: { type: 'summary_text', text: '' },\n });\n } else if (kind === 'message') {\n this.itemId = `msg_${this.outputIndex}`;\n this.emit('response.output_item.added', {\n output_index: this.outputIndex,\n item: { type: 'message', id: this.itemId, status: 'in_progress', role: 'assistant', content: [] },\n });\n this.emit('response.content_part.added', {\n item_id: this.itemId, output_index: this.outputIndex, content_index: 0,\n part: { type: 'output_text', annotations: [], text: '' },\n });\n }\n }\n\n onChunk(chunk) {\n this.start(chunk.model);\n if (chunk.usage) this.usage = mapUsage(chunk.usage);\n const delta = chunk.choices?.[0]?.delta;\n if (!delta) return;\n\n if (delta.reasoning_content) {\n this.openItem('reasoning');\n this.reasoning += delta.reasoning_content;\n this.emit('response.reasoning_summary_text.delta', {\n item_id: this.itemId, output_index: this.outputIndex, summary_index: 0,\n delta: delta.reasoning_content,\n });\n }\n if (delta.content) {\n this.openItem('message');\n this.text += delta.content;\n this.emit('response.output_text.delta', {\n item_id: this.itemId, output_index: this.outputIndex, content_index: 0,\n delta: delta.content,\n });\n }\n for (const tc of delta.tool_calls || []) {\n const idx = tc.index ?? 0;\n let call = this.calls.get(idx);\n if (!call) {\n this.closeCurrent();\n this.outputIndex++;\n call = {\n itemId: `fc_${this.outputIndex}`,\n callId: tc.id || `call_${this.outputIndex}`,\n name: tc.function?.name || '',\n args: '',\n outputIndex: this.outputIndex,\n };\n this.calls.set(idx, call);\n this.emit('response.output_item.added', {\n output_index: call.outputIndex,\n item: {\n type: 'function_call', id: call.itemId, status: 'in_progress',\n call_id: call.callId, name: call.name, arguments: '',\n },\n });\n } else if (tc.function?.name) {\n call.name += tc.function.name;\n }\n // Upstream may send the real id after our placeholder was created.\n if (tc.id && tc.id !== call.callId && call.callId.startsWith('call_')) {\n call.callId = tc.id;\n }\n if (tc.function?.arguments) {\n call.args += tc.function.arguments;\n this.emit('response.function_call_arguments.delta', {\n item_id: call.itemId, output_index: call.outputIndex, delta: tc.function.arguments,\n });\n }\n }\n }\n\n finish(finishReason) {\n this.closeCurrent();\n for (const call of this.calls.values()) {\n const item = {\n type: 'function_call', id: call.itemId, status: 'completed',\n call_id: call.callId, name: call.name, arguments: call.args,\n };\n this.emit('response.function_call_arguments.done', {\n item_id: call.itemId, output_index: call.outputIndex, arguments: call.args,\n });\n this.emit('response.output_item.done', { output_index: call.outputIndex, item });\n this.output.push(item);\n }\n this.calls.clear();\n const status = finishReason === 'length' ? 'incomplete' : 'completed';\n const response = this.snapshot(status, true);\n if (status === 'incomplete') response.incomplete_details = { reason: 'max_output_tokens' };\n this.emit(`response.${status}`, { response });\n }\n\n fail(message) {\n this.start('');\n const response = this.snapshot('failed', true);\n response.error = { code: 'upstream_error', message };\n this.emit('response.failed', { response });\n }\n}\n\n// ---- HTTP server -------------------------------------------------------------\n\nasync function handleResponses(provider, body, req, res) {\n const upstream = UPSTREAMS[provider];\n const chatBody = toChatBody(body);\n const t0 = Date.now();\n\n const upstreamRes = await fetch(upstream, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': req.headers['authorization'] || '',\n },\n body: JSON.stringify(chatBody),\n signal: AbortSignal.timeout(UPSTREAM_TIMEOUT_MS),\n });\n\n if (!upstreamRes.ok) {\n const errText = await upstreamRes.text();\n console.log(`[${provider}] ${chatBody.model} -> HTTP ${upstreamRes.status} (${Date.now() - t0}ms)`);\n res.writeHead(upstreamRes.status, { 'Content-Type': 'application/json' });\n let message = errText;\n try { message = JSON.parse(errText).error?.message || errText; } catch {}\n res.end(JSON.stringify({ error: { type: 'upstream_error', code: String(upstreamRes.status), message } }));\n return;\n }\n\n if (!chatBody.stream) {\n const chatResp = await upstreamRes.json();\n console.log(`[${provider}] ${chatBody.model} -> 200 non-stream (${Date.now() - t0}ms)`);\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(toResponseObject(chatResp)));\n return;\n }\n\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n });\n const translator = new StreamTranslator(s => res.write(s));\n let finishReason = null;\n let buffer = '';\n const decoder = new TextDecoder();\n\n try {\n for await (const raw of upstreamRes.body) {\n buffer += decoder.decode(raw, { stream: true });\n let nl;\n while ((nl = buffer.indexOf('\\n')) !== -1) {\n const line = buffer.slice(0, nl).trim();\n buffer = buffer.slice(nl + 1);\n if (!line.startsWith('data:')) continue;\n const data = line.slice(5).trim();\n if (data === '[DONE]') continue;\n let chunk;\n try { chunk = JSON.parse(data); } catch { continue; }\n if (chunk.choices?.[0]?.finish_reason) finishReason = chunk.choices[0].finish_reason;\n translator.onChunk(chunk);\n }\n }\n translator.finish(finishReason);\n console.log(`[${provider}] ${chatBody.model} -> 200 stream done (${Date.now() - t0}ms)`);\n } catch (err) {\n translator.fail(String(err?.message || err));\n console.log(`[${provider}] ${chatBody.model} -> stream error: ${err?.message} (${Date.now() - t0}ms)`);\n }\n res.end();\n}\n\nconst server = http.createServer((req, res) => {\n if (req.method === 'GET' && req.url === '/health') {\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ ok: true, providers: Object.keys(UPSTREAMS) }));\n return;\n }\n\n const m = req.method === 'POST' && req.url.match(/^\\/([a-z]+)\\/v1\\/responses$/);\n if (!m || !UPSTREAMS[m[1]]) {\n res.writeHead(404, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: { type: 'not_found', message: `Unknown route ${req.method} ${req.url}. Providers: ${Object.keys(UPSTREAMS).join(', ')}` } }));\n return;\n }\n\n const chunks = [];\n let bodySize = 0;\n req.on('data', c => {\n bodySize += c.length;\n if (bodySize > MAX_BODY_SIZE) {\n if (!res.headersSent) {\n res.writeHead(413, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: { type: 'too_large', message: `Body exceeds ${MAX_BODY_SIZE / 1024 / 1024} MB limit` } }));\n }\n req.destroy();\n return;\n }\n chunks.push(c);\n });\n req.on('end', () => {\n let body;\n try { body = JSON.parse(Buffer.concat(chunks).toString('utf8')); }\n catch {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: { type: 'invalid_request', message: 'Body is not valid JSON' } }));\n return;\n }\n handleResponses(m[1], body, req, res).catch(err => {\n console.error(`[${m[1]}] fatal:`, err);\n if (!res.headersSent) {\n res.writeHead(502, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: { type: 'adapter_error', message: String(err?.message || err) } }));\n } else {\n res.end();\n }\n });\n });\n});\n\nserver.listen(PORT, '127.0.0.1', () => {\n console.log(`codex-adapter listening on http://127.0.0.1:${PORT}`);\n console.log(`providers: ${Object.keys(UPSTREAMS).join(', ')}`);\n console.log(`route: POST /<provider>/v1/responses`);\n});\n"}}, "kmclaude": {"c07db31916dca8077b9124f5c098258f9607b016": {"t": 1785846824.453782, "n": 4037, "h": "e839ee54e8d8ba0b", "c": "#!/usr/bin/env bash\n# shellcheck disable=SC2034 # variables consumed by lib/common.sh\n# kmclaude — launch Claude Code on Moonshot AI Kimi's Anthropic-compatible API.\n#\n# Uses the official Kimi Anthropic-compatible endpoint:\n# https://api.moonshot.cn/anthropic\n#\n# Reads KIMI_API_KEY (or MOONSHOT_API_KEY) from the environment first,\n# then falls back to ~/.zshrc / ~/.bashrc / ~/.bash_profile / ~/.profile.\n#\n# Quick start (no install needed):\n# chmod +x kmclaude\n# ./kmclaude\n#\n# Optional — make it globally available:\n# sudo mv kmclaude /usr/local/bin/ && sudo chmod +x /usr/local/bin/kmclaude\n#\n# Use:\n# kmclaude # start on kimi-k3 (Kimi flagship)\n# kmclaude fast # start on kimi-k2.5 (cheaper / faster tier)\n# kmclaude long # (no-op; 1M context is the default)\n# kmclaude effort max # set reasoning effort (low|medium|high|xhigh|max)\n# kmclaude update # git pull latest from this repo\n# kmclaude --help # any remaining flag is forwarded to claude\n#\n# Optional env overrides:\n# KIMI_MODEL=kimi-k3 # main model\n# KIMI_FLASH_MODEL=kimi-k2.5 # flash / haiku / subagent tier\n# KIMI_BASE_URL=https://.../anthropic # custom Anthropic-compatible base URL\n# KIMI_CTX=1048576 # max context tokens (default: 1M)\n# KIMI_OUTPUT=8000 # cap output tokens\n# KIMI_EFFORT=max # CLAUDE_CODE_EFFORT_LEVEL\n#\n# In-session switch:\n# /model kimi-k2.5 # switch to the flash tier\n# /model kimi-k3 # switch back to pro\n#\nset -euo pipefail\n\n# Resolve symlink to find the real script directory.\n_SELF=\"$0\"\nif [ -L \"$_SELF\" ]; then\n _LINK=\"$(readlink \"$_SELF\")\"\n case \"$_LINK\" in\n /*) _SELF=\"$_LINK\" ;;\n *) _SELF=\"$(cd \"$(dirname \"$_SELF\")\" && pwd)/$_LINK\" ;;\n esac\nfi\nSELF_DIR=\"$(cd \"$(dirname \"$_SELF\")\" && pwd)\"\nif [ -f \"$SELF_DIR/lib/common.sh\" ]; then source \"$SELF_DIR/lib/common.sh\"\nelif [ -f \"$SELF_DIR/../lib/common.sh\" ]; then source \"$SELF_DIR/../lib/common.sh\"\nelse echo \"kmclaude: cannot find lib/common.sh. Reinstall or cd to repo.\" >&2; exit 1; fi\n\ncheck_version \"kmclaude\" \"$@\"\n\nPRO_MODEL=\"${KIMI_MODEL:-kimi-k3}\"\nFLASH_MODEL=\"${KIMI_FLASH_MODEL:-kimi-k2.5}\"\n\n# Handle the update subcommand before the API-key check so it works key-less.\nif [ $# -gt 0 ] && [ \"$1\" = \"update\" ]; then\n do_update \"kmclaude\" \"KMCLAUDE_HOME\"\nfi\n\nAPI_KEY=\"$(resolve_api_key \"KIMI_API_KEY\")\"\n[ -z \"$API_KEY\" ] && API_KEY=\"$(resolve_api_key \"MOONSHOT_API_KEY\")\"\nif [ -z \"$API_KEY\" ]; then\n echo \"❌ Neither KIMI_API_KEY nor MOONSHOT_API_KEY found.\" >&2\n echo \" Add one line to ~/.zshrc or ~/.bashrc:\" >&2\n echo \" export MOONSHOT_API_KEY=sk-xxxxxxxxxxxxxxxxxx\" >&2\n echo \" Get your key at: https://platform.moonshot.cn/console/api-keys\" >&2\n exit 1\nfi\n\nBASE_URL=\"${KIMI_BASE_URL:-https://api.moonshot.cn/anthropic}\"\n\nLONG_CTX=0\nEFFORT=\"${KIMI_EFFORT:-}\"\n\n# Positional alias: `fast`/`flash` runs the flash tier as the main model.\nMAIN_MODEL=\"$PRO_MODEL\"\nwhile [ $# -gt 0 ]; do\n case \"$1\" in\n fast|flash) MAIN_MODEL=\"$FLASH_MODEL\"; shift ;;\n long) LONG_CTX=1; shift ;;\n effort)\n case \"${2:-}\" in\n low|medium|high|xhigh|max) EFFORT=\"$2\"; shift 2 ;;\n *) echo \"kmclaude: invalid effort level '${2:-}'. Use: low medium high xhigh max\" >&2; exit 1 ;;\n esac\n ;;\n --) shift; break ;;\n *) break ;;\n esac\ndone\n\n# Surface the other model in Claude Code's /model picker for mid-session switching.\nif [ \"$MAIN_MODEL\" = \"$PRO_MODEL\" ]; then\n OTHER_MODEL=\"$FLASH_MODEL\"\n OTHER_DESC=\"Kimi K2.5 — fast / cheap tier\"\nelse\n OTHER_MODEL=\"$PRO_MODEL\"\n OTHER_DESC=\"Kimi K3 — full reasoning\"\nfi\n\nexport_anthropic_base\n# Subagents run on the cheaper flash tier.\nexport CLAUDE_CODE_SUBAGENT_MODEL=\"$FLASH_MODEL\"\nset_custom_model \"$OTHER_MODEL\" \"$MAIN_MODEL\" \"$OTHER_DESC\"\n\nCTX=\"${KIMI_CTX:-1048576}\"\nOUTPUT_CAP=\"${KIMI_OUTPUT:-}\"\napply_context_and_effort\n\nshow_banner_and_launch \"Kimi\" \"$@\"\n"}}}} |