#!/usr/bin/env bash # arkclaude-desktop — configure Claude Desktop to use Volcengine Ark (Coding Plan) as inference backend. # # Edits ~/Library/Application Support/Claude-3p/configLibrary/{_meta,}.json # and restarts Claude Desktop. macOS only. # # Usage: # arkclaude-desktop # configure to Ark (doubao-seed-2.0-code) and restart # arkclaude-desktop plus # use doubao-seed-2.0-pro # arkclaude-desktop kimi # use kimi-k2.7-code # arkclaude-desktop deepseek # use deepseek-v4-pro # arkclaude-desktop glm # use glm-5.2 # arkclaude-desktop minimax # use minimax-m2.7 # arkclaude-desktop update # git pull latest from the repo # arkclaude-desktop -h # help # # Reads ARK_API_KEY from env or ~/.zshrc & friends (else prompts). The base URL # defaults to https://ark.cn-beijing.volces.com/api/coding; override with ARK_BASE_URL. # # Note: Once a third-party gateway is active, Claude Desktop's Chat mode is # unavailable — only Cowork (3P) and Code modes work. set -euo pipefail CONFIG_DIR="$HOME/Library/Application Support/Claude-3p/configLibrary" META="$CONFIG_DIR/_meta.json" ENTRY_NAME="arkclaude-desktop" AUTH_SCHEME="bearer" MAIN_MODEL="doubao-seed-2.0-code" FAST_MODEL="doubao-seed-2.0-lite" MODEL_LABEL="doubao-seed-2.0-code" while [[ $# -gt 0 ]]; do case "$1" in -h|--help) sed -n '2,26p' "$0" | sed 's/^# \{0,1\}//' exit 0 ;; update) SELF_DIR="$(cd "$(dirname "$0")" && pwd)" echo "arkclaude-desktop: pulling latest from $SELF_DIR ..." git -C "$SELF_DIR" pull && echo "arkclaude-desktop: updated." || { echo "arkclaude-desktop: git pull failed. Check network or resolve conflicts manually." >&2 exit 1 } exit 0 ;; max|pro|code) MAIN_MODEL="doubao-seed-2.0-code"; MODEL_LABEL="doubao-seed-2.0-code"; FAST_MODEL="doubao-seed-2.0-lite"; shift ;; plus) MAIN_MODEL="doubao-seed-2.0-pro"; MODEL_LABEL="doubao-seed-2.0-pro"; FAST_MODEL="doubao-seed-2.0-lite"; shift ;; fast|flash|lite) MAIN_MODEL="doubao-seed-2.0-lite"; MODEL_LABEL="doubao-seed-2.0-lite"; FAST_MODEL="doubao-seed-2.0-lite"; shift ;; kimi) MAIN_MODEL="kimi-k2.7-code"; MODEL_LABEL="Kimi K2.7 Code"; FAST_MODEL="doubao-seed-2.0-lite"; shift ;; kimi-pro|kimi-k2) MAIN_MODEL="kimi-k2.6"; MODEL_LABEL="Kimi K2.6"; FAST_MODEL="kimi-k2.6"; shift ;; deepseek) MAIN_MODEL="deepseek-v4-pro"; MODEL_LABEL="DeepSeek V4 Pro"; FAST_MODEL="deepseek-v4-flash"; shift ;; deepseek-flash) MAIN_MODEL="deepseek-v4-flash"; MODEL_LABEL="DeepSeek V4 Flash"; FAST_MODEL="deepseek-v4-flash"; shift ;; glm) MAIN_MODEL="glm-5.2"; MODEL_LABEL="GLM 5.2"; FAST_MODEL="glm-5.2"; shift ;; minimax) MAIN_MODEL="minimax-m2.7"; MODEL_LABEL="MiniMax M2.7"; FAST_MODEL="minimax-m2.7"; shift ;; *) echo "arkclaude-desktop: unknown argument: $1" >&2 echo "Run 'arkclaude-desktop -h' for usage." >&2 exit 2 ;; esac done preflight() { if [[ "$(uname)" != "Darwin" ]]; then echo "arkclaude-desktop: macOS only." >&2 exit 1 fi if [[ ! -d "/Applications/Claude.app" ]]; then echo "arkclaude-desktop: /Applications/Claude.app not found. Install from https://claude.ai/download." >&2 exit 1 fi if [[ ! -x "/usr/bin/jq" ]]; then echo "arkclaude-desktop: /usr/bin/jq not found (required on macOS Sonoma+)." >&2 exit 1 fi local dev_settings="$HOME/Library/Application Support/Claude/developer_settings.json" if [[ ! -f "$dev_settings" ]] \ || ! /usr/bin/jq -e '.allowDevTools == true' "$dev_settings" >/dev/null 2>&1; then cat >&2 <<'EOF' arkclaude-desktop: Developer Mode not enabled in Claude Desktop. Claude Desktop's third-party inference feature is gated behind Developer Mode. Enable it once in the GUI before running this script: 1. Open Claude Desktop 2. Help → Troubleshooting → Enable Developer Mode 3. Re-run arkclaude-desktop EOF exit 1 fi } resolve_api_key() { if [[ -n "${ARK_API_KEY:-}" ]]; then printf '%s' "$ARK_API_KEY" return 0 fi local rc found="" for rc in "$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.bash_profile" "$HOME/.profile"; do [[ -r "$rc" ]] || continue found="$(grep -v '^[[:space:]]*#' "$rc" 2>/dev/null \ | grep -E '^[[:space:]]*export[[:space:]]+ARK_API_KEY=' \ | tail -1 \ | sed -E 's/^[^=]*=//; s/^"(.*)"$/\1/; s/^'\''(.*)'\''$/\1/' \ || true)" if [[ -n "$found" ]]; then printf '%s' "$found" return 0 fi done local key key="$(osascript <<'APPLESCRIPT' 2>/dev/null || true try set theKey to text returned of (display dialog ¬ "ARK API Key not found in env or shell rc.\nPaste your Volcengine Ark API Key:" ¬ default answer "" ¬ with hidden answer ¬ with title "arkclaude-desktop") return theKey on error return "" end try APPLESCRIPT )" if [[ -z "$key" ]]; then echo "arkclaude-desktop: no ARK API Key provided. Aborting." >&2 exit 1 fi printf '%s' "$key" } confirm_or_abort() { echo echo "About to: $1" echo "Press Enter to continue, Ctrl-C to abort." read -r _ } write_entry() { local uuid="$1" local entry_path="$CONFIG_DIR/${uuid}.json" local tmp="${entry_path}.tmp" local content content="$(jq -n \ --arg baseUrl "$BASE_URL" \ --arg apiKey "$ARK_KEY" \ --arg auth "$AUTH_SCHEME" \ --arg main "$MAIN_MODEL" \ --arg fast "$FAST_MODEL" \ '{ 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)) }')" printf '%s' "$content" > "$tmp" chmod 600 "$tmp" mv "$tmp" "$entry_path" } ensure_meta_entry() { mkdir -p "$CONFIG_DIR" local existing_uuid="" if [[ -f "$META" ]]; then existing_uuid="$(jq -r --arg name "$ENTRY_NAME" \ '.entries[]? | select(.name==$name) | .id' "$META" 2>/dev/null \ | head -1)" fi local uuid if [[ -n "$existing_uuid" ]]; then uuid="$existing_uuid" else uuid="$(uuidgen | tr 'A-Z' 'a-z')" fi local tmp="${META}.tmp" local content if [[ -f "$META" ]]; then content="$(jq --arg id "$uuid" --arg name "$ENTRY_NAME" ' .appliedId = $id | .entries = ((.entries // []) | map(select(.name != $name)) + [{id: $id, name: $name}]) ' "$META")" else content="$(jq -n --arg id "$uuid" --arg name "$ENTRY_NAME" \ '{appliedId: $id, entries: [{id: $id, name: $name}]}')" fi printf '%s' "$content" > "$tmp" chmod 600 "$tmp" mv "$tmp" "$META" printf '%s' "$uuid" } restart_claude() { killall Claude 2>/dev/null || true sleep 1 open -a Claude } BASE_URL="${ARK_BASE_URL:-https://ark.cn-beijing.volces.com/api/coding}" preflight ARK_KEY="$(resolve_api_key)" confirm_or_abort "configure Claude Desktop to use Ark Coding Plan ($BASE_URL, $MODEL_LABEL) and restart it." UUID="$(ensure_meta_entry)" write_entry "$UUID" restart_claude cat <