1 line
33 KiB
JSON
1 line
33 KiB
JSON
{"repo": "bh4me/claude-code-mimo-deepseek-installer", "files": {"README.md": {"e69f3725ec4306aef1ec05237a475956692d6ec4": {"t": 1785595273.0922694, "n": 3018, "h": "e3ad32fc59179377", "c": "# Claude Code MiMo / DeepSeek Installer\n\n一键安装 Claude Code,并配置 DeepSeek 或 Xiaomi MiMo 的 Anthropic-compatible API。默认先配置 DeepSeek。API key 只保存在本机,不会上传到 GitHub。\n\n## 快速安装\n\nmacOS / Linux:\n\n```bash\ncurl -fsSL https://github.com/BH4ME/claude-code-mimo-deepseek-installer/releases/latest/download/install.sh | bash\n```\n\nWindows PowerShell:\n\n```powershell\nirm https://github.com/BH4ME/claude-code-mimo-deepseek-installer/releases/latest/download/install.ps1 | iex\n```\n\n非交互安装:\n\n```bash\nDEEPSEEK_API_KEY=\"sk-...\" ./install.sh\n```\n\nPowerShell:\n\n```powershell\n$env:DEEPSEEK_API_KEY=\"sk-...\"\n.\\install.ps1\n```\n\n如果你还想一起保存 MiMo key,后面再加上:\n\n```bash\nMIMO_API_KEY=\"sk-or-tp-...\" DEEPSEEK_API_KEY=\"sk-...\" ./install.sh\n```\n\n只安装 Claude Code 和切换命令,暂不写 key:\n\n```bash\n./install.sh --skip-api-key\n```\n\n默认安装完成后会切到 `deepseek-v4-pro`。可以用 `DEEPSEEK_MODEL` 覆盖。\n\n## 切换\n\nMiMo:\n\n```bash\nclaude-provider mimo flash\nclaude-provider mimo pro\nclaude-provider mimo omni\n```\n\nDeepSeek:\n\n```bash\nDEEPSEEK_API_KEY=\"sk-...\" claude-provider deepseek pro\nclaude-provider deepseek flash\n```\n\n也可以直接用完整模型名:\n\n```bash\nclaude-provider mimo mimo-v2.5-pro\nclaude-provider deepseek deepseek-v4-pro\n```\n\n快捷别名:\n\n| Provider | Alias | Model |\n| --- | --- | --- |\n| MiMo | `flash` | `mimo-v2-flash` |\n| MiMo | `pro` | `mimo-v2.5-pro` |\n| MiMo | `omni` | `mimo-v2.5` |\n| DeepSeek | `flash` | `deepseek-v4-flash` |\n| DeepSeek | `pro` | `deepseek-v4-pro` |\n\n切换后重新运行:\n\n```bash\nclaude\n```\n\n## API Key\n\n保存或更换 key:\n\n```bash\nclaude-provider-key mimo \"sk-or-tp-...\"\nclaude-provider-key deepseek \"sk-...\"\n```\n\n如果当前 provider 正在使用这个 key,脚本会同步更新 `~/.claude/settings.json`。否则会先保存在 `~/.claude/provider-switch.json`,下次切换时生效。\n\nMiMo base URL 会按 key 自动判断:\n\n| Key | Base URL |\n| --- | --- |\n| `sk-...` | `https://api.xiaomimimo.com/anthropic` |\n| `tp-...` | `https://token-plan-cn.xiaomimimo.com/anthropic` |\n\n需要专属 URL 时设置 `MIMO_ANTHROPIC_BASE_URL`。\n\n## 写入内容\n\n脚本会写入:\n\n- `~/.claude/settings.json`: Claude Code 实际读取的 API 配置。\n- `~/.claude/provider-switch.json`: 每个 provider 的 key 和 base URL。\n- `~/.claude.json`: 标记 Claude Code 已完成 onboarding。\n\n## 常见问题\n\n如果提示 `command not found: claude-provider`,先打开新终端再试。macOS / Linux 安装脚本会把 `~/.local/bin` 写入 shell profile;仍不生效时可临时运行:\n\n```bash\nexport PATH=\"$HOME/.local/bin:$PATH\"\n~/.local/bin/claude-provider mimo pro\n```\n\n如果提示 `Missing API key for mimo`:\n\n```bash\nclaude-provider-key mimo \"sk-or-tp-...\"\nclaude-provider mimo pro\n```\n\n如果 Claude Code 卡在 `Retrying in ... attempt .../10`:\n\n```bash\nCtrl+C\nclaude-provider-key mimo \"sk-or-tp-...\"\nclaude-provider mimo pro\ncat ~/.claude/settings.json\n```\n\n确认 `settings.json` 里已经有:\n\n- `ANTHROPIC_API_KEY`\n- `ANTHROPIC_BASE_URL`\n- `ANTHROPIC_MODEL`\n\n然后重新运行:\n\n```bash\nclaude\n```\n\n如果启动页仍然显示官方 `pro / API Usage Billing`,通常说明 Claude 还在用旧会话。先退出旧进程再重开:\n\n```bash\npkill -f claude\nclaude\n```\n\nWindows 如果 `claude` 无法识别,重开 PowerShell/CMD。仍不行时检查:\n\n```powershell\n& \"$HOME\\.claude-provider\\claude.cmd\" --version\n& \"$HOME\\.local\\bin\\claude.exe\" --version\n```\n\nLinux 如果官方安装脚本被拦截,本安装器会自动尝试 npm fallback;Node/npm 不可用时会尝试系统包管理器或用户本地 Node.js。\n"}}, "set-provider-key.sh": {"e69f3725ec4306aef1ec05237a475956692d6ec4": {"t": 1785745966.6080534, "n": 5144, "h": "b8e0f1029ccbda08", "c": "#!/usr/bin/env bash\nset -euo pipefail\n\nPROVIDER_ARG=\"${1:-}\"\nTOKEN_ARG=\"${2:-}\"\nPROVIDER_FILE=\"${HOME}/.claude/provider-switch.json\"\nSETTINGS_FILE=\"${HOME}/.claude/settings.json\"\n\nusage() {\n cat <<'USAGE'\nUsage:\n claude-provider-key mimo [api-key]\n claude-provider-key deepseek [api-key]\n\nEnvironment:\n MIMO_API_KEY Xiaomi MiMo API key\n DEEPSEEK_API_KEY DeepSeek API key\n\nExamples:\n claude-provider-key mimo\n claude-provider-key deepseek sk-...\n DEEPSEEK_API_KEY=\"sk-...\" claude-provider-key deepseek\nUSAGE\n}\n\nget_mimo_base_url() {\n local token=\"${1:-}\"\n if [ -n \"${MIMO_ANTHROPIC_BASE_URL:-}\" ]; then\n printf '%s\\n' \"${MIMO_ANTHROPIC_BASE_URL}\"\n elif [[ \"${token}\" == tp-* ]]; then\n printf '%s\\n' \"https://token-plan-cn.xiaomimimo.com/anthropic\"\n else\n printf '%s\\n' \"https://api.xiaomimimo.com/anthropic\"\n fi\n}\n\ncase \"${PROVIDER_ARG}\" in\n mimo|xiaomi-mimo)\n PROVIDER=\"mimo\"\n TOKEN=\"${TOKEN_ARG:-${MIMO_API_KEY:-}}\"\n ;;\n deepseek|ds)\n PROVIDER=\"deepseek\"\n TOKEN=\"${TOKEN_ARG:-${DEEPSEEK_API_KEY:-}}\"\n ;;\n --help|-h|\"\")\n usage\n exit 0\n ;;\n *)\n echo \"Unknown provider: ${PROVIDER_ARG}\" >&2\n echo \"Use: mimo or deepseek\" >&2\n exit 1\n ;;\nesac\n\nif [ -z \"${TOKEN}\" ]; then\n if [ ! -r /dev/tty ]; then\n echo \"API key is required. Pass it as an argument or environment variable.\" >&2\n exit 1\n fi\n printf \"Enter ${PROVIDER} API key: \"\n stty -echo < /dev/tty\n read -r TOKEN < /dev/tty\n stty echo < /dev/tty\n printf \"\\n\"\nfi\n\nif [ -z \"${TOKEN}\" ]; then\n echo \"API key is required.\" >&2\n exit 1\nfi\n\nmkdir -p \"$(dirname \"${PROVIDER_FILE}\")\"\n\nexport PROVIDER\nexport TOKEN\nif [ \"${PROVIDER}\" = \"mimo\" ]; then\n BASE_URL=\"$(get_mimo_base_url \"${TOKEN}\")\"\nelse\n BASE_URL=\"\"\nfi\nexport BASE_URL\nexport PROVIDER_FILE\nexport SETTINGS_FILE\n\nif command -v python3 >/dev/null 2>&1; then\n python3 <<'PY'\nimport json\nimport os\nimport shutil\nimport time\n\nprovider = os.environ[\"PROVIDER\"]\ntoken = os.environ[\"TOKEN\"]\nbase_url = os.environ.get(\"BASE_URL\", \"\")\nprovider_file = os.environ[\"PROVIDER_FILE\"]\nsettings_file = os.environ[\"SETTINGS_FILE\"]\n\ndef read_json(path):\n if not os.path.exists(path):\n return {}\n try:\n with open(path, encoding=\"utf-8\") as handle:\n return json.load(handle)\n except Exception:\n backup = f\"{path}.bak.{int(time.time() * 1000)}\"\n shutil.copy2(path, backup)\n print(f\"Existing JSON was invalid. Backed up to {backup}\")\n return {}\n\nprovider_config = read_json(provider_file)\nprovider_config[\"providers\"] = provider_config.get(\"providers\", {})\nprovider_config[\"providers\"][provider] = {\n **provider_config[\"providers\"].get(provider, {}),\n \"authToken\": token,\n}\nif base_url:\n provider_config[\"providers\"][provider][\"baseUrl\"] = base_url\n\nwith open(provider_file, \"w\", encoding=\"utf-8\") as handle:\n json.dump(provider_config, handle, indent=2)\n handle.write(\"\\n\")\n\nif provider_config.get(\"activeProvider\") == provider and os.path.exists(settings_file):\n settings = read_json(settings_file)\n settings[\"env\"] = {\n **settings.get(\"env\", {}),\n \"ANTHROPIC_API_KEY\": token,\n }\n settings[\"env\"].pop(\"ANTHROPIC_AUTH_TOKEN\", None)\n if base_url:\n settings[\"env\"][\"ANTHROPIC_BASE_URL\"] = base_url\n with open(settings_file, \"w\", encoding=\"utf-8\") as handle:\n json.dump(settings, handle, indent=2)\n handle.write(\"\\n\")\nPY\nelif command -v node >/dev/null 2>&1; then\n node <<'NODE'\nconst fs = require(\"fs\");\n\nconst provider = process.env.PROVIDER;\nconst token = process.env.TOKEN;\nconst baseUrl = process.env.BASE_URL || \"\";\nconst providerFile = process.env.PROVIDER_FILE;\nconst settingsFile = process.env.SETTINGS_FILE;\n\nfunction readJson(file) {\n if (!fs.existsSync(file)) return {};\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch (error) {\n const backup = `${file}.bak.${Date.now()}`;\n fs.copyFileSync(file, backup);\n console.warn(`Existing JSON was invalid. Backed up to ${backup}`);\n return {};\n }\n}\n\nconst providerConfig = readJson(providerFile);\nproviderConfig.providers = providerConfig.providers || {};\nproviderConfig.providers[provider] = {\n ...(providerConfig.providers[provider] || {}),\n authToken: token,\n};\nif (baseUrl) {\n providerConfig.providers[provider].baseUrl = baseUrl;\n}\n\nfs.writeFileSync(providerFile, `${JSON.stringify(providerConfig, null, 2)}\\n`, { mode: 0o600 });\n\nif (providerConfig.activeProvider === provider && fs.existsSync(settingsFile)) {\n const settings = readJson(settingsFile);\n settings.env = {\n ...(settings.env || {}),\n ANTHROPIC_API_KEY: token,\n };\n delete settings.env.ANTHROPIC_AUTH_TOKEN;\n if (baseUrl) {\n settings.env.ANTHROPIC_BASE_URL = baseUrl;\n }\n fs.writeFileSync(settingsFile, `${JSON.stringify(settings, null, 2)}\\n`, { mode: 0o600 });\n}\nNODE\nelse\n echo \"Neither python3 nor node is available. Cannot update JSON settings safely.\" >&2\n exit 1\nfi\n\nchmod 600 \"${PROVIDER_FILE}\" \"${SETTINGS_FILE}\" 2>/dev/null || true\necho \"Saved API key for provider: ${PROVIDER}\"\necho \"If ${PROVIDER} is active, Claude Code settings were updated too.\"\n"}, "f4f95ff5840f86ff0b8a1492f6271b9bcdf8525b": {"t": 1785758352.6544201, "n": 5144, "h": "b8e0f1029ccbda08", "c": "#!/usr/bin/env bash\nset -euo pipefail\n\nPROVIDER_ARG=\"${1:-}\"\nTOKEN_ARG=\"${2:-}\"\nPROVIDER_FILE=\"${HOME}/.claude/provider-switch.json\"\nSETTINGS_FILE=\"${HOME}/.claude/settings.json\"\n\nusage() {\n cat <<'USAGE'\nUsage:\n claude-provider-key mimo [api-key]\n claude-provider-key deepseek [api-key]\n\nEnvironment:\n MIMO_API_KEY Xiaomi MiMo API key\n DEEPSEEK_API_KEY DeepSeek API key\n\nExamples:\n claude-provider-key mimo\n claude-provider-key deepseek sk-...\n DEEPSEEK_API_KEY=\"sk-...\" claude-provider-key deepseek\nUSAGE\n}\n\nget_mimo_base_url() {\n local token=\"${1:-}\"\n if [ -n \"${MIMO_ANTHROPIC_BASE_URL:-}\" ]; then\n printf '%s\\n' \"${MIMO_ANTHROPIC_BASE_URL}\"\n elif [[ \"${token}\" == tp-* ]]; then\n printf '%s\\n' \"https://token-plan-cn.xiaomimimo.com/anthropic\"\n else\n printf '%s\\n' \"https://api.xiaomimimo.com/anthropic\"\n fi\n}\n\ncase \"${PROVIDER_ARG}\" in\n mimo|xiaomi-mimo)\n PROVIDER=\"mimo\"\n TOKEN=\"${TOKEN_ARG:-${MIMO_API_KEY:-}}\"\n ;;\n deepseek|ds)\n PROVIDER=\"deepseek\"\n TOKEN=\"${TOKEN_ARG:-${DEEPSEEK_API_KEY:-}}\"\n ;;\n --help|-h|\"\")\n usage\n exit 0\n ;;\n *)\n echo \"Unknown provider: ${PROVIDER_ARG}\" >&2\n echo \"Use: mimo or deepseek\" >&2\n exit 1\n ;;\nesac\n\nif [ -z \"${TOKEN}\" ]; then\n if [ ! -r /dev/tty ]; then\n echo \"API key is required. Pass it as an argument or environment variable.\" >&2\n exit 1\n fi\n printf \"Enter ${PROVIDER} API key: \"\n stty -echo < /dev/tty\n read -r TOKEN < /dev/tty\n stty echo < /dev/tty\n printf \"\\n\"\nfi\n\nif [ -z \"${TOKEN}\" ]; then\n echo \"API key is required.\" >&2\n exit 1\nfi\n\nmkdir -p \"$(dirname \"${PROVIDER_FILE}\")\"\n\nexport PROVIDER\nexport TOKEN\nif [ \"${PROVIDER}\" = \"mimo\" ]; then\n BASE_URL=\"$(get_mimo_base_url \"${TOKEN}\")\"\nelse\n BASE_URL=\"\"\nfi\nexport BASE_URL\nexport PROVIDER_FILE\nexport SETTINGS_FILE\n\nif command -v python3 >/dev/null 2>&1; then\n python3 <<'PY'\nimport json\nimport os\nimport shutil\nimport time\n\nprovider = os.environ[\"PROVIDER\"]\ntoken = os.environ[\"TOKEN\"]\nbase_url = os.environ.get(\"BASE_URL\", \"\")\nprovider_file = os.environ[\"PROVIDER_FILE\"]\nsettings_file = os.environ[\"SETTINGS_FILE\"]\n\ndef read_json(path):\n if not os.path.exists(path):\n return {}\n try:\n with open(path, encoding=\"utf-8\") as handle:\n return json.load(handle)\n except Exception:\n backup = f\"{path}.bak.{int(time.time() * 1000)}\"\n shutil.copy2(path, backup)\n print(f\"Existing JSON was invalid. Backed up to {backup}\")\n return {}\n\nprovider_config = read_json(provider_file)\nprovider_config[\"providers\"] = provider_config.get(\"providers\", {})\nprovider_config[\"providers\"][provider] = {\n **provider_config[\"providers\"].get(provider, {}),\n \"authToken\": token,\n}\nif base_url:\n provider_config[\"providers\"][provider][\"baseUrl\"] = base_url\n\nwith open(provider_file, \"w\", encoding=\"utf-8\") as handle:\n json.dump(provider_config, handle, indent=2)\n handle.write(\"\\n\")\n\nif provider_config.get(\"activeProvider\") == provider and os.path.exists(settings_file):\n settings = read_json(settings_file)\n settings[\"env\"] = {\n **settings.get(\"env\", {}),\n \"ANTHROPIC_API_KEY\": token,\n }\n settings[\"env\"].pop(\"ANTHROPIC_AUTH_TOKEN\", None)\n if base_url:\n settings[\"env\"][\"ANTHROPIC_BASE_URL\"] = base_url\n with open(settings_file, \"w\", encoding=\"utf-8\") as handle:\n json.dump(settings, handle, indent=2)\n handle.write(\"\\n\")\nPY\nelif command -v node >/dev/null 2>&1; then\n node <<'NODE'\nconst fs = require(\"fs\");\n\nconst provider = process.env.PROVIDER;\nconst token = process.env.TOKEN;\nconst baseUrl = process.env.BASE_URL || \"\";\nconst providerFile = process.env.PROVIDER_FILE;\nconst settingsFile = process.env.SETTINGS_FILE;\n\nfunction readJson(file) {\n if (!fs.existsSync(file)) return {};\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch (error) {\n const backup = `${file}.bak.${Date.now()}`;\n fs.copyFileSync(file, backup);\n console.warn(`Existing JSON was invalid. Backed up to ${backup}`);\n return {};\n }\n}\n\nconst providerConfig = readJson(providerFile);\nproviderConfig.providers = providerConfig.providers || {};\nproviderConfig.providers[provider] = {\n ...(providerConfig.providers[provider] || {}),\n authToken: token,\n};\nif (baseUrl) {\n providerConfig.providers[provider].baseUrl = baseUrl;\n}\n\nfs.writeFileSync(providerFile, `${JSON.stringify(providerConfig, null, 2)}\\n`, { mode: 0o600 });\n\nif (providerConfig.activeProvider === provider && fs.existsSync(settingsFile)) {\n const settings = readJson(settingsFile);\n settings.env = {\n ...(settings.env || {}),\n ANTHROPIC_API_KEY: token,\n };\n delete settings.env.ANTHROPIC_AUTH_TOKEN;\n if (baseUrl) {\n settings.env.ANTHROPIC_BASE_URL = baseUrl;\n }\n fs.writeFileSync(settingsFile, `${JSON.stringify(settings, null, 2)}\\n`, { mode: 0o600 });\n}\nNODE\nelse\n echo \"Neither python3 nor node is available. Cannot update JSON settings safely.\" >&2\n exit 1\nfi\n\nchmod 600 \"${PROVIDER_FILE}\" \"${SETTINGS_FILE}\" 2>/dev/null || true\necho \"Saved API key for provider: ${PROVIDER}\"\necho \"If ${PROVIDER} is active, Claude Code settings were updated too.\"\n"}, "032ee832a28dc4ac7e4bc47757841f68eefc3257": {"t": 1785758354.3788462, "n": 5118, "h": "cb0dc55ebcef5744", "c": "#!/usr/bin/env bash\nset -euo pipefail\n\nPROVIDER_ARG=\"${1:-}\"\nTOKEN_ARG=\"${2:-}\"\nPROVIDER_FILE=\"${HOME}/.claude/provider-switch.json\"\nSETTINGS_FILE=\"${HOME}/.claude/settings.json\"\n\nusage() {\n cat <<'USAGE'\nUsage:\n claude-provider-key mimo [api-key]\n claude-provider-key deepseek [api-key]\n\nEnvironment:\n MIMO_API_KEY Xiaomi MiMo API key\n DEEPSEEK_API_KEY DeepSeek API key\n\nExamples:\n claude-provider-key mimo\n claude-provider-key deepseek sk-...\n DEEPSEEK_API_KEY=\"sk-...\" claude-provider-key deepseek\nUSAGE\n}\n\nget_mimo_base_url() {\n local token=\"${1:-}\"\n if [ -n \"${MIMO_ANTHROPIC_BASE_URL:-}\" ]; then\n printf '%s\\n' \"${MIMO_ANTHROPIC_BASE_URL}\"\n elif [[ \"${token}\" == tp-* ]]; then\n printf '%s\\n' \"https://token-plan-cn.xiaomimimo.com/anthropic\"\n else\n printf '%s\\n' \"https://api.xiaomimimo.com/anthropic\"\n fi\n}\n\ncase \"${PROVIDER_ARG}\" in\n mimo|xiaomi-mimo)\n PROVIDER=\"mimo\"\n TOKEN=\"${TOKEN_ARG:-${MIMO_API_KEY:-}}\"\n ;;\n deepseek|ds)\n PROVIDER=\"deepseek\"\n TOKEN=\"${TOKEN_ARG:-${DEEPSEEK_API_KEY:-}}\"\n ;;\n --help|-h|\"\")\n usage\n exit 0\n ;;\n *)\n echo \"Unknown provider: ${PROVIDER_ARG}\" >&2\n echo \"Use: mimo or deepseek\" >&2\n exit 1\n ;;\nesac\n\nif [ -z \"${TOKEN}\" ]; then\n if [ ! -r /dev/tty ]; then\n echo \"API key is required. Pass it as an argument or environment variable.\" >&2\n exit 1\n fi\n printf \"Enter ${PROVIDER} API key: \"\n stty -echo < /dev/tty\n read -r TOKEN < /dev/tty\n stty echo < /dev/tty\n printf \"\\n\"\nfi\n\nif [ -z \"${TOKEN}\" ]; then\n echo \"API key is required.\" >&2\n exit 1\nfi\n\nmkdir -p \"$(dirname \"${PROVIDER_FILE}\")\"\n\nexport PROVIDER\nexport TOKEN\nif [ \"${PROVIDER}\" = \"mimo\" ]; then\n BASE_URL=\"$(get_mimo_base_url \"${TOKEN}\")\"\nelse\n BASE_URL=\"\"\nfi\nexport BASE_URL\nexport PROVIDER_FILE\nexport SETTINGS_FILE\n\nif command -v python3 >/dev/null 2>&1; then\n python3 <<'PY'\nimport json\nimport os\nimport shutil\nimport time\n\nprovider = os.environ[\"PROVIDER\"]\ntoken = os.environ[\"TOKEN\"]\nbase_url = os.environ.get(\"BASE_URL\", \"\")\nprovider_file = os.environ[\"PROVIDER_FILE\"]\nsettings_file = os.environ[\"SETTINGS_FILE\"]\n\ndef read_json(path):\n if not os.path.exists(path):\n return {}\n try:\n with open(path, encoding=\"utf-8\") as handle:\n return json.load(handle)\n except Exception:\n backup = f\"{path}.bak.{int(time.time() * 1000)}\"\n shutil.copy2(path, backup)\n print(f\"Existing JSON was invalid. Backed up to {backup}\")\n return {}\n\nprovider_config = read_json(provider_file)\nprovider_config[\"providers\"] = provider_config.get(\"providers\", {})\nprovider_config[\"providers\"][provider] = {\n **provider_config[\"providers\"].get(provider, {}),\n \"authToken\": token,\n}\nif base_url:\n provider_config[\"providers\"][provider][\"baseUrl\"] = base_url\n\nwith open(provider_file, \"w\", encoding=\"utf-8\") as handle:\n json.dump(provider_config, handle, indent=2)\n handle.write(\"\\n\")\n\nif provider_config.get(\"activeProvider\") == provider and os.path.exists(settings_file):\n settings = read_json(settings_file)\n settings[\"env\"] = {\n **settings.get(\"env\", {}),\n \"ANTHROPIC_API_KEY\": token,\n \"ANTHROPIC_AUTH_TOKEN\": token,\n }\n if base_url:\n settings[\"env\"][\"ANTHROPIC_BASE_URL\"] = base_url\n with open(settings_file, \"w\", encoding=\"utf-8\") as handle:\n json.dump(settings, handle, indent=2)\n handle.write(\"\\n\")\nPY\nelif command -v node >/dev/null 2>&1; then\n node <<'NODE'\nconst fs = require(\"fs\");\n\nconst provider = process.env.PROVIDER;\nconst token = process.env.TOKEN;\nconst baseUrl = process.env.BASE_URL || \"\";\nconst providerFile = process.env.PROVIDER_FILE;\nconst settingsFile = process.env.SETTINGS_FILE;\n\nfunction readJson(file) {\n if (!fs.existsSync(file)) return {};\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch (error) {\n const backup = `${file}.bak.${Date.now()}`;\n fs.copyFileSync(file, backup);\n console.warn(`Existing JSON was invalid. Backed up to ${backup}`);\n return {};\n }\n}\n\nconst providerConfig = readJson(providerFile);\nproviderConfig.providers = providerConfig.providers || {};\nproviderConfig.providers[provider] = {\n ...(providerConfig.providers[provider] || {}),\n authToken: token,\n};\nif (baseUrl) {\n providerConfig.providers[provider].baseUrl = baseUrl;\n}\n\nfs.writeFileSync(providerFile, `${JSON.stringify(providerConfig, null, 2)}\\n`, { mode: 0o600 });\n\nif (providerConfig.activeProvider === provider && fs.existsSync(settingsFile)) {\n const settings = readJson(settingsFile);\n settings.env = {\n ...(settings.env || {}),\n ANTHROPIC_API_KEY: token,\n ANTHROPIC_AUTH_TOKEN: token,\n };\n if (baseUrl) {\n settings.env.ANTHROPIC_BASE_URL = baseUrl;\n }\n fs.writeFileSync(settingsFile, `${JSON.stringify(settings, null, 2)}\\n`, { mode: 0o600 });\n}\nNODE\nelse\n echo \"Neither python3 nor node is available. Cannot update JSON settings safely.\" >&2\n exit 1\nfi\n\nchmod 600 \"${PROVIDER_FILE}\" \"${SETTINGS_FILE}\" 2>/dev/null || true\necho \"Saved API key for provider: ${PROVIDER}\"\necho \"If ${PROVIDER} is active, Claude Code settings were updated too.\"\n"}, "b3da3944f9d17009569d35bf8d0f723a98fb1c79": {"t": 1785758355.5456214, "n": 5052, "h": "91fd5bc091c2f882", "c": "#!/usr/bin/env bash\nset -euo pipefail\n\nPROVIDER_ARG=\"${1:-}\"\nTOKEN_ARG=\"${2:-}\"\nPROVIDER_FILE=\"${HOME}/.claude/provider-switch.json\"\nSETTINGS_FILE=\"${HOME}/.claude/settings.json\"\n\nusage() {\n cat <<'USAGE'\nUsage:\n claude-provider-key mimo [api-key]\n claude-provider-key deepseek [api-key]\n\nEnvironment:\n MIMO_API_KEY Xiaomi MiMo API key\n DEEPSEEK_API_KEY DeepSeek API key\n\nExamples:\n claude-provider-key mimo\n claude-provider-key deepseek sk-...\n DEEPSEEK_API_KEY=\"sk-...\" claude-provider-key deepseek\nUSAGE\n}\n\nget_mimo_base_url() {\n local token=\"${1:-}\"\n if [ -n \"${MIMO_ANTHROPIC_BASE_URL:-}\" ]; then\n printf '%s\\n' \"${MIMO_ANTHROPIC_BASE_URL}\"\n elif [[ \"${token}\" == tp-* ]]; then\n printf '%s\\n' \"https://token-plan-cn.xiaomimimo.com/anthropic\"\n else\n printf '%s\\n' \"https://api.xiaomimimo.com/anthropic\"\n fi\n}\n\ncase \"${PROVIDER_ARG}\" in\n mimo|xiaomi-mimo)\n PROVIDER=\"mimo\"\n TOKEN=\"${TOKEN_ARG:-${MIMO_API_KEY:-}}\"\n ;;\n deepseek|ds)\n PROVIDER=\"deepseek\"\n TOKEN=\"${TOKEN_ARG:-${DEEPSEEK_API_KEY:-}}\"\n ;;\n --help|-h|\"\")\n usage\n exit 0\n ;;\n *)\n echo \"Unknown provider: ${PROVIDER_ARG}\" >&2\n echo \"Use: mimo or deepseek\" >&2\n exit 1\n ;;\nesac\n\nif [ -z \"${TOKEN}\" ]; then\n if [ ! -r /dev/tty ]; then\n echo \"API key is required. Pass it as an argument or environment variable.\" >&2\n exit 1\n fi\n printf \"Enter ${PROVIDER} API key: \"\n stty -echo < /dev/tty\n read -r TOKEN < /dev/tty\n stty echo < /dev/tty\n printf \"\\n\"\nfi\n\nif [ -z \"${TOKEN}\" ]; then\n echo \"API key is required.\" >&2\n exit 1\nfi\n\nmkdir -p \"$(dirname \"${PROVIDER_FILE}\")\"\n\nexport PROVIDER\nexport TOKEN\nif [ \"${PROVIDER}\" = \"mimo\" ]; then\n BASE_URL=\"$(get_mimo_base_url \"${TOKEN}\")\"\nelse\n BASE_URL=\"\"\nfi\nexport BASE_URL\nexport PROVIDER_FILE\nexport SETTINGS_FILE\n\nif command -v python3 >/dev/null 2>&1; then\n python3 <<'PY'\nimport json\nimport os\nimport shutil\nimport time\n\nprovider = os.environ[\"PROVIDER\"]\ntoken = os.environ[\"TOKEN\"]\nbase_url = os.environ.get(\"BASE_URL\", \"\")\nprovider_file = os.environ[\"PROVIDER_FILE\"]\nsettings_file = os.environ[\"SETTINGS_FILE\"]\n\ndef read_json(path):\n if not os.path.exists(path):\n return {}\n try:\n with open(path, encoding=\"utf-8\") as handle:\n return json.load(handle)\n except Exception:\n backup = f\"{path}.bak.{int(time.time() * 1000)}\"\n shutil.copy2(path, backup)\n print(f\"Existing JSON was invalid. Backed up to {backup}\")\n return {}\n\nprovider_config = read_json(provider_file)\nprovider_config[\"providers\"] = provider_config.get(\"providers\", {})\nprovider_config[\"providers\"][provider] = {\n **provider_config[\"providers\"].get(provider, {}),\n \"authToken\": token,\n}\nif base_url:\n provider_config[\"providers\"][provider][\"baseUrl\"] = base_url\n\nwith open(provider_file, \"w\", encoding=\"utf-8\") as handle:\n json.dump(provider_config, handle, indent=2)\n handle.write(\"\\n\")\n\nif provider_config.get(\"activeProvider\") == provider and os.path.exists(settings_file):\n settings = read_json(settings_file)\n settings[\"env\"] = {\n **settings.get(\"env\", {}),\n \"ANTHROPIC_AUTH_TOKEN\": token,\n }\n if base_url:\n settings[\"env\"][\"ANTHROPIC_BASE_URL\"] = base_url\n with open(settings_file, \"w\", encoding=\"utf-8\") as handle:\n json.dump(settings, handle, indent=2)\n handle.write(\"\\n\")\nPY\nelif command -v node >/dev/null 2>&1; then\n node <<'NODE'\nconst fs = require(\"fs\");\n\nconst provider = process.env.PROVIDER;\nconst token = process.env.TOKEN;\nconst baseUrl = process.env.BASE_URL || \"\";\nconst providerFile = process.env.PROVIDER_FILE;\nconst settingsFile = process.env.SETTINGS_FILE;\n\nfunction readJson(file) {\n if (!fs.existsSync(file)) return {};\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch (error) {\n const backup = `${file}.bak.${Date.now()}`;\n fs.copyFileSync(file, backup);\n console.warn(`Existing JSON was invalid. Backed up to ${backup}`);\n return {};\n }\n}\n\nconst providerConfig = readJson(providerFile);\nproviderConfig.providers = providerConfig.providers || {};\nproviderConfig.providers[provider] = {\n ...(providerConfig.providers[provider] || {}),\n authToken: token,\n};\nif (baseUrl) {\n providerConfig.providers[provider].baseUrl = baseUrl;\n}\n\nfs.writeFileSync(providerFile, `${JSON.stringify(providerConfig, null, 2)}\\n`, { mode: 0o600 });\n\nif (providerConfig.activeProvider === provider && fs.existsSync(settingsFile)) {\n const settings = readJson(settingsFile);\n settings.env = {\n ...(settings.env || {}),\n ANTHROPIC_AUTH_TOKEN: token,\n };\n if (baseUrl) {\n settings.env.ANTHROPIC_BASE_URL = baseUrl;\n }\n fs.writeFileSync(settingsFile, `${JSON.stringify(settings, null, 2)}\\n`, { mode: 0o600 });\n}\nNODE\nelse\n echo \"Neither python3 nor node is available. Cannot update JSON settings safely.\" >&2\n exit 1\nfi\n\nchmod 600 \"${PROVIDER_FILE}\" \"${SETTINGS_FILE}\" 2>/dev/null || true\necho \"Saved API key for provider: ${PROVIDER}\"\necho \"If ${PROVIDER} is active, Claude Code settings were updated too.\"\n"}, "9a2c351ee4c33e1466a91b49e0ccbbea0e24b584": {"t": 1785758356.8358042, "n": 4236, "h": "14765e51e0ec9736", "c": "#!/usr/bin/env bash\nset -euo pipefail\n\nPROVIDER_ARG=\"${1:-}\"\nTOKEN_ARG=\"${2:-}\"\nPROVIDER_FILE=\"${HOME}/.claude/provider-switch.json\"\nSETTINGS_FILE=\"${HOME}/.claude/settings.json\"\n\nusage() {\n cat <<'USAGE'\nUsage:\n claude-provider-key mimo [api-key]\n claude-provider-key deepseek [api-key]\n\nEnvironment:\n MIMO_API_KEY Xiaomi MiMo API key\n DEEPSEEK_API_KEY DeepSeek API key\n\nExamples:\n claude-provider-key mimo\n claude-provider-key deepseek sk-...\n DEEPSEEK_API_KEY=\"sk-...\" claude-provider-key deepseek\nUSAGE\n}\n\ncase \"${PROVIDER_ARG}\" in\n mimo|xiaomi-mimo)\n PROVIDER=\"mimo\"\n TOKEN=\"${TOKEN_ARG:-${MIMO_API_KEY:-}}\"\n ;;\n deepseek|ds)\n PROVIDER=\"deepseek\"\n TOKEN=\"${TOKEN_ARG:-${DEEPSEEK_API_KEY:-}}\"\n ;;\n --help|-h|\"\")\n usage\n exit 0\n ;;\n *)\n echo \"Unknown provider: ${PROVIDER_ARG}\" >&2\n echo \"Use: mimo or deepseek\" >&2\n exit 1\n ;;\nesac\n\nif [ -z \"${TOKEN}\" ]; then\n if [ ! -r /dev/tty ]; then\n echo \"API key is required. Pass it as an argument or environment variable.\" >&2\n exit 1\n fi\n printf \"Enter ${PROVIDER} API key: \"\n stty -echo < /dev/tty\n read -r TOKEN < /dev/tty\n stty echo < /dev/tty\n printf \"\\n\"\nfi\n\nif [ -z \"${TOKEN}\" ]; then\n echo \"API key is required.\" >&2\n exit 1\nfi\n\nmkdir -p \"$(dirname \"${PROVIDER_FILE}\")\"\n\nexport PROVIDER\nexport TOKEN\nexport PROVIDER_FILE\nexport SETTINGS_FILE\n\nif command -v python3 >/dev/null 2>&1; then\n python3 <<'PY'\nimport json\nimport os\nimport shutil\nimport time\n\nprovider = os.environ[\"PROVIDER\"]\ntoken = os.environ[\"TOKEN\"]\nprovider_file = os.environ[\"PROVIDER_FILE\"]\nsettings_file = os.environ[\"SETTINGS_FILE\"]\n\ndef read_json(path):\n if not os.path.exists(path):\n return {}\n try:\n with open(path, encoding=\"utf-8\") as handle:\n return json.load(handle)\n except Exception:\n backup = f\"{path}.bak.{int(time.time() * 1000)}\"\n shutil.copy2(path, backup)\n print(f\"Existing JSON was invalid. Backed up to {backup}\")\n return {}\n\nprovider_config = read_json(provider_file)\nprovider_config[\"providers\"] = provider_config.get(\"providers\", {})\nprovider_config[\"providers\"][provider] = {\n **provider_config[\"providers\"].get(provider, {}),\n \"authToken\": token,\n}\n\nwith open(provider_file, \"w\", encoding=\"utf-8\") as handle:\n json.dump(provider_config, handle, indent=2)\n handle.write(\"\\n\")\n\nif provider_config.get(\"activeProvider\") == provider and os.path.exists(settings_file):\n settings = read_json(settings_file)\n settings[\"env\"] = {\n **settings.get(\"env\", {}),\n \"ANTHROPIC_AUTH_TOKEN\": token,\n }\n with open(settings_file, \"w\", encoding=\"utf-8\") as handle:\n json.dump(settings, handle, indent=2)\n handle.write(\"\\n\")\nPY\nelif command -v node >/dev/null 2>&1; then\n node <<'NODE'\nconst fs = require(\"fs\");\n\nconst provider = process.env.PROVIDER;\nconst token = process.env.TOKEN;\nconst providerFile = process.env.PROVIDER_FILE;\nconst settingsFile = process.env.SETTINGS_FILE;\n\nfunction readJson(file) {\n if (!fs.existsSync(file)) return {};\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch (error) {\n const backup = `${file}.bak.${Date.now()}`;\n fs.copyFileSync(file, backup);\n console.warn(`Existing JSON was invalid. Backed up to ${backup}`);\n return {};\n }\n}\n\nconst providerConfig = readJson(providerFile);\nproviderConfig.providers = providerConfig.providers || {};\nproviderConfig.providers[provider] = {\n ...(providerConfig.providers[provider] || {}),\n authToken: token,\n};\n\nfs.writeFileSync(providerFile, `${JSON.stringify(providerConfig, null, 2)}\\n`, { mode: 0o600 });\n\nif (providerConfig.activeProvider === provider && fs.existsSync(settingsFile)) {\n const settings = readJson(settingsFile);\n settings.env = {\n ...(settings.env || {}),\n ANTHROPIC_AUTH_TOKEN: token,\n };\n fs.writeFileSync(settingsFile, `${JSON.stringify(settings, null, 2)}\\n`, { mode: 0o600 });\n}\nNODE\nelse\n echo \"Neither python3 nor node is available. Cannot update JSON settings safely.\" >&2\n exit 1\nfi\n\nchmod 600 \"${PROVIDER_FILE}\" \"${SETTINGS_FILE}\" 2>/dev/null || true\necho \"Saved API key for provider: ${PROVIDER}\"\necho \"If ${PROVIDER} is active, Claude Code settings were updated too.\"\n"}, "12abafbde8b03da838cafc3caa7c901b2c83ca89": {"t": 1785758359.432033, "n": 2716, "h": "b53307c014b6e299", "c": "#!/usr/bin/env bash\nset -euo pipefail\n\nPROVIDER_ARG=\"${1:-}\"\nTOKEN_ARG=\"${2:-}\"\nPROVIDER_FILE=\"${HOME}/.claude/provider-switch.json\"\nSETTINGS_FILE=\"${HOME}/.claude/settings.json\"\n\nusage() {\n cat <<'USAGE'\nUsage:\n claude-provider-key mimo [api-key]\n claude-provider-key deepseek [api-key]\n\nEnvironment:\n MIMO_API_KEY Xiaomi MiMo API key\n DEEPSEEK_API_KEY DeepSeek API key\n\nExamples:\n claude-provider-key mimo\n claude-provider-key deepseek sk-...\n DEEPSEEK_API_KEY=\"sk-...\" claude-provider-key deepseek\nUSAGE\n}\n\ncase \"${PROVIDER_ARG}\" in\n mimo|xiaomi-mimo)\n PROVIDER=\"mimo\"\n TOKEN=\"${TOKEN_ARG:-${MIMO_API_KEY:-}}\"\n ;;\n deepseek|ds)\n PROVIDER=\"deepseek\"\n TOKEN=\"${TOKEN_ARG:-${DEEPSEEK_API_KEY:-}}\"\n ;;\n --help|-h|\"\")\n usage\n exit 0\n ;;\n *)\n echo \"Unknown provider: ${PROVIDER_ARG}\" >&2\n echo \"Use: mimo or deepseek\" >&2\n exit 1\n ;;\nesac\n\nif [ -z \"${TOKEN}\" ]; then\n if [ ! -r /dev/tty ]; then\n echo \"API key is required. Pass it as an argument or environment variable.\" >&2\n exit 1\n fi\n printf \"Enter ${PROVIDER} API key: \"\n stty -echo < /dev/tty\n read -r TOKEN < /dev/tty\n stty echo < /dev/tty\n printf \"\\n\"\nfi\n\nif [ -z \"${TOKEN}\" ]; then\n echo \"API key is required.\" >&2\n exit 1\nfi\n\nmkdir -p \"$(dirname \"${PROVIDER_FILE}\")\"\n\nexport PROVIDER\nexport TOKEN\nexport PROVIDER_FILE\nexport SETTINGS_FILE\n\nnode <<'NODE'\nconst fs = require(\"fs\");\n\nconst provider = process.env.PROVIDER;\nconst token = process.env.TOKEN;\nconst providerFile = process.env.PROVIDER_FILE;\nconst settingsFile = process.env.SETTINGS_FILE;\n\nfunction readJson(file) {\n if (!fs.existsSync(file)) return {};\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch (error) {\n const backup = `${file}.bak.${Date.now()}`;\n fs.copyFileSync(file, backup);\n console.warn(`Existing JSON was invalid. Backed up to ${backup}`);\n return {};\n }\n}\n\nconst providerConfig = readJson(providerFile);\nproviderConfig.providers = providerConfig.providers || {};\nproviderConfig.providers[provider] = {\n ...(providerConfig.providers[provider] || {}),\n authToken: token,\n};\n\nfs.writeFileSync(providerFile, `${JSON.stringify(providerConfig, null, 2)}\\n`, { mode: 0o600 });\n\nif (providerConfig.activeProvider === provider && fs.existsSync(settingsFile)) {\n const settings = readJson(settingsFile);\n settings.env = {\n ...(settings.env || {}),\n ANTHROPIC_AUTH_TOKEN: token,\n };\n fs.writeFileSync(settingsFile, `${JSON.stringify(settings, null, 2)}\\n`, { mode: 0o600 });\n}\nNODE\n\nchmod 600 \"${PROVIDER_FILE}\" \"${SETTINGS_FILE}\" 2>/dev/null || true\necho \"Saved API key for provider: ${PROVIDER}\"\necho \"If ${PROVIDER} is active, Claude Code settings were updated too.\"\n"}}}} |