ClaudeCode-Deployment-for-HarmonyOS
Health Uyari
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Uyari
- process.env — Environment variable access in anthropic-proxy.mjs
- network request — Outbound network request in anthropic-proxy.mjs
- process.env — Environment variable access in tests/proxy.test.mjs
- network request — Outbound network request in tests/proxy.test.mjs
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
A complete tutorial for deploying Claude Code in HarmonyOS PC, including router for OpenAI-compatible API format.
Deploy Claude Code from Scratch — Full Guide (with Multi-Model Slots + Dual-Channel + Agent Tool Calls)
This guide relies only on the system's built-in Node.js and npm. A lightweight pure Node.js script running locally elegantly translates Claude Code's complex bidirectional tool-call requests, Thinking inference, and SSE streams to OpenAI (or any OpenAI-compatible endpoint such as DeepSeek), enabling one-click startup with automatic cleanup on exit.
For detailed technical documentation on the proxy script (protocol conversion rules, SSE streaming state machine, Reasoning degradation mechanism, etc.), see anthropic-proxy-script-documentation.md.
1. Prerequisites
Install DevNode-OH from the Huawei AppGallery.
Run the following commands in the terminal to verify the minimum environment requirements:
node -v # requires >= 18
npm -v # requires >= 9
2. Create the Protocol Conversion Proxy Script
Create ~/anthropic-proxy.mjs in your home directory. This script listens on 127.0.0.1:4000 and performs seamless bidirectional translation of text conversations, Thinking inference, and Tool Use calls, with 4 model slot dynamic routing and primary/backup dual API channels.
vim ~/anthropic-proxy.mjs
Copy the entire content of anthropic-proxy.mjs from this project into the file (zero third-party dependencies, ready to run). Core capabilities include:
- Full bidirectional translation between Anthropic Messages and OpenAI Chat Completions
- Bidirectional SSE streaming conversion (thinking block, text block, tool_use block), strictly sequential blocks
- Content fidelity: images (including those nested in
tool_result), documents,top_p/stop_sequences— anything unsupported is logged instead of silently dropped - 4-slot model routing: Default / Sonnet / Opus / Haiku, each independently configurable with upstream model and reasoning depth
- Primary/backup dual API channels (PRIMARY / SECONDARY): slot-level traffic distribution plus automatic one-shot failover on transport errors, 429 and 5xx
- Anthropic direct pass-through mode (automatically skips protocol conversion when all APIs use Anthropic format)
- Tool ID bidirectional normalization (
toolu_oai_xxx↔call_xxx) - Reasoning degradation retry (
max → high → remove parameter) - 30-second SSE keepalive heartbeat in both pass-through and conversion modes
- Two-level timeouts: connect/response-header (
PROXY_TIMEOUT_MS) plus an idle watchdog covering the whole stream (PROXY_IDLE_TIMEOUT_MS) - Request body limit (default 64 MiB, clean
413) and a localhost Origin/Host access guard with an optionalPROXY_AUTH_TOKEN POST /v1/messages/count_tokens: upstream pass-through on Anthropic channels, local estimate on OpenAI channels- Bilingual (en / zh-CN) output with fixed-priority language resolution: explicit
--lang/PROXY_LANG→ system locale → English fallback
Make the script executable:
chmod +x ~/anthropic-proxy.mjs
Optionally, run the regression suite from a checkout of this project:
node --test tests/proxy.test.mjs
3. Configure Zsh Shell Function
Edit ~/.zshrc:
vim ~/.zshrc
Append the following code at the end of the file. Be sure to modify the API Core Configuration and Model Slot Configuration sections according to your actual setup:
# ╔══════════════════════════════════════════════════════════════╗
# ║ Claude Code Proxy Gateway Launcher ║
# ╚══════════════════════════════════════════════════════════════╝
claude() {
# ┌─────────────────────────────────────────────────────────────┐
# │ 1. API Core Configuration │
# └─────────────────────────────────────────────────────────────┘
# ▸ Primary API Configuration
local PRIMARY_API_FORMAT="openai" # Protocol format: "openai" or "anthropic"
local PRIMARY_AUTH_TYPE="api-key" # Auth type: "api-key" or "bearer"
local PRIMARY_API_KEY="sk-your-primary-key" # Auth key
local PRIMARY_BASE_URL="https://api.openai.com" # API endpoint
# ▸ Backup API Configuration
local ENABLE_SECONDARY_API="false" # Enable backup API: slot routing + automatic failover
local SECONDARY_API_FORMAT="openai" # Protocol format: "openai" or "anthropic"
local SECONDARY_AUTH_TYPE="api-key" # Auth type: "api-key" or "bearer"
local SECONDARY_API_KEY="sk-your-secondary-key" # Backup auth key
local SECONDARY_BASE_URL="https://api.openai.com" # Backup API endpoint
# ┌─────────────────────────────────────────────────────────────┐
# │ 2. Model Slot Configuration (4 slots × dual channel) │
# └─────────────────────────────────────────────────────────────┘
# ▸ Slot 1: Default Model
local Client_Model_Default="claude-sonnet-5" # Client-requested model name
local Upstream_Model_Default="deepseek-flash" # Actual upstream model name for forwarding
local API_for_Default="PRIMARY" # API channel (PRIMARY/SECONDARY)
local REASONING_for_Default="auto" # Reasoning depth (auto/max/high/medium/low/none)
# └ auto: maps based on budget_tokens, defaults to medium when no budget set
# ▸ Slot 2: Sonnet Model
local Client_Model_Sonnet="claude-sonnet-5"
local Upstream_Model_Sonnet="deepseek-flash"
local API_for_Sonnet="PRIMARY"
local REASONING_for_Sonnet="auto"
# ▸ Slot 3: Opus Model
local Client_Model_Opus="claude-opus-5"
local Upstream_Model_Opus="deepseek-pro"
local API_for_Opus="PRIMARY"
local REASONING_for_Opus="auto"
# ▸ Slot 4: Haiku Model (sub-agent slot)
local Client_Model_Haiku="claude-haiku-4-5"
local Upstream_Model_Haiku="deepseek-flash"
local API_for_Haiku="PRIMARY"
local REASONING_for_Haiku="medium" # Haiku doesn't support reasoning depth setting in Claude Code, so manual configuration is recommended
# ┌─────────────────────────────────────────────────────────────┐
# │ 3. Pre-Start Initialization │
# └─────────────────────────────────────────────────────────────┘
# ── Clean up residual environment variables from the previous run ──
unset ANTHROPIC_BASE_URL ANTHROPIC_API_KEY ANTHROPIC_AUTH_TOKEN
unset ANTHROPIC_SKIP_CONNECTIVITY_CHECK CLAUDE_CODE_SKIP_CONNECTIVITY_CHECK
unset ANTHROPIC_MODEL ANTHROPIC_DEFAULT_SONNET_MODEL ANTHROPIC_DEFAULT_OPUS_MODEL ANTHROPIC_DEFAULT_HAIKU_MODEL
unset CLAUDE_CODE_SUBAGENT_MODEL CLAUDE_CODE_EFFORT_LEVEL
# ── Kill residual proxy via PID file (verify port 4000 is occupied first to avoid false kills after reboot) ──
local PID_FILE="$HOME/.anthropic-proxy.pid"
if [[ -f "$PID_FILE" ]]; then
if node -e "
require('net').connect(4000,'127.0.0.1',()=>process.exit(0))
.on('error',()=>process.exit(1))
.setTimeout(1000,()=>process.exit(1));
" 2>/dev/null; then
kill "$(cat "$PID_FILE")" 2>/dev/null
fi
rm -f "$PID_FILE"
fi
sleep 0.3
# ┌─────────────────────────────────────────────────────────────┐
# │ 4. Proxy Environment Initialization │
# └─────────────────────────────────────────────────────────────┘
local PROXY_PORT=4000
local PROXY_SCRIPT="$HOME/anthropic-proxy.mjs"
local PROXY_PID=""
local PROXY_LANG="en"
# ── Null-value checks for required configuration ──
if [[ -z "$PRIMARY_API_KEY" || "$PRIMARY_API_KEY" == "sk-your-primary-key" ]]; then
echo "[Gateway] Error: PRIMARY_API_KEY is not configured. Please set it in ~/.zshrc"
return 1
fi
if [[ -z "$PRIMARY_BASE_URL" ]]; then
echo "[Gateway] Error: PRIMARY_BASE_URL is not configured"
return 1
fi
if [[ -z "$Upstream_Model_Default" ]]; then
echo "[Gateway] Error: Upstream default model is not configured"
return 1
fi
if [[ ! -f "$PROXY_SCRIPT" ]]; then
echo "[Gateway] Proxy script not found: $PROXY_SCRIPT"
return 1
fi
# ▸ Detect pass-through mode (skip proxy when both APIs use native Anthropic protocol with matching configs)
local CAN_BYPASS_PROXY="false"
if [[ "$PRIMARY_API_FORMAT" == "anthropic" ]]; then
if [[ "$ENABLE_SECONDARY_API" != "true" ]]; then
CAN_BYPASS_PROXY="true"
elif [[ "$SECONDARY_API_FORMAT" == "anthropic" && "$PRIMARY_BASE_URL" == "$SECONDARY_BASE_URL" && "$PRIMARY_API_KEY" == "$SECONDARY_API_KEY" ]]; then
CAN_BYPASS_PROXY="true"
fi
fi
# ╔══════════════════════════════════════════════════════════════╗
# ║ Mode A: Anthropic Direct Pass-Through (skip proxy) ║
# ╚══════════════════════════════════════════════════════════════╝
if [[ "$CAN_BYPASS_PROXY" == "true" ]]; then
echo "[Gateway] Anthropic direct mode, skipping proxy..."
export ANTHROPIC_BASE_URL="$PRIMARY_BASE_URL"
export ANTHROPIC_AUTH_TOKEN="$PRIMARY_API_KEY"
export ANTHROPIC_SKIP_CONNECTIVITY_CHECK=1
export CLAUDE_CODE_SKIP_CONNECTIVITY_CHECK=1
# ── Set upstream real model names ─
export ANTHROPIC_MODEL="$Upstream_Model_Default"
export ANTHROPIC_DEFAULT_SONNET_MODEL="$Upstream_Model_Sonnet"
export ANTHROPIC_DEFAULT_OPUS_MODEL="$Upstream_Model_Opus"
export ANTHROPIC_DEFAULT_HAIKU_MODEL="$Upstream_Model_Haiku"
export CLAUDE_CODE_SUBAGENT_MODEL="$Upstream_Model_Haiku"
# ╔══════════════════════════════════════════════════════════════╗
# ║ Mode B: Proxy Gateway Mode (start Node for protocol conv.) ║
# ╚══════════════════════════════════════════════════════════════╝
else
echo "[Gateway] Starting protocol conversion proxy..."
# ── Pass slot and API configurations to the Node proxy via env vars ──
# ── Optional hardening vars can simply be exported in your shell: ──
# ── PROXY_AUTH_TOKEN, MAX_BODY_BYTES, ALLOWED_ORIGINS, ALLOWED_HOSTS, ──
# ── STREAM_INCLUDE_USAGE, CONVERT_PDF_TO_FILE ──
CLIENT_MODEL_DEFAULT="$Client_Model_Default" \
UPSTREAM_MODEL_DEFAULT="$Upstream_Model_Default" \
MODEL_DEFAULT_API="$API_for_Default" \
MODEL_DEFAULT_REASONING="$REASONING_for_Default" \
\
CLIENT_MODEL_SONNET="$Client_Model_Sonnet" \
UPSTREAM_MODEL_SONNET="$Upstream_Model_Sonnet" \
MODEL_SONNET_API="$API_for_Sonnet" \
MODEL_SONNET_REASONING="$REASONING_for_Sonnet" \
\
CLIENT_MODEL_OPUS="$Client_Model_Opus" \
UPSTREAM_MODEL_OPUS="$Upstream_Model_Opus" \
MODEL_OPUS_API="$API_for_Opus" \
MODEL_OPUS_REASONING="$REASONING_for_Opus" \
\
CLIENT_MODEL_HAIKU="$Client_Model_Haiku" \
UPSTREAM_MODEL_HAIKU="$Upstream_Model_Haiku" \
MODEL_HAIKU_API="$API_for_Haiku" \
MODEL_HAIKU_REASONING="$REASONING_for_Haiku" \
\
PRIMARY_API_FORMAT="$PRIMARY_API_FORMAT" \
PRIMARY_AUTH_TYPE="$PRIMARY_AUTH_TYPE" \
PRIMARY_API_KEY="$PRIMARY_API_KEY" \
PRIMARY_BASE_URL="$PRIMARY_BASE_URL" \
\
ENABLE_SECONDARY_API="$ENABLE_SECONDARY_API" \
SECONDARY_API_FORMAT="$SECONDARY_API_FORMAT" \
SECONDARY_AUTH_TYPE="$SECONDARY_AUTH_TYPE" \
SECONDARY_API_KEY="$SECONDARY_API_KEY" \
SECONDARY_BASE_URL="$SECONDARY_BASE_URL" \
\
PROXY_LANG="$PROXY_LANG" \
PROXY_TIMEOUT_MS="${PROXY_TIMEOUT_MS:-300000}" \
PROXY_IDLE_TIMEOUT_MS="${PROXY_IDLE_TIMEOUT_MS:-120000}" \
PORT="$PROXY_PORT" \
nohup node "$PROXY_SCRIPT" > $HOME/.anthropic-proxy.log 2>&1 &
PROXY_PID=$!
echo "$PROXY_PID" > "$HOME/.anthropic-proxy.pid"
sleep 2.5
# ── Health check ──
if ! kill -0 "$PROXY_PID" 2>/dev/null; then
echo "[Gateway] Failed to start. Last 12 lines of log:"
tail -12 "$HOME/.anthropic-proxy.log"
return 1
fi
echo "[Gateway] Started (127.0.0.1:${PROXY_PORT})"
echo ""
export ANTHROPIC_BASE_URL="http://127.0.0.1:${PROXY_PORT}"
# When PROXY_AUTH_TOKEN is set, export the same token value here instead
export ANTHROPIC_API_KEY="sk-ant-mock-key-to-local-proxy"
export ANTHROPIC_SKIP_CONNECTIVITY_CHECK=1
export CLAUDE_CODE_SKIP_CONNECTIVITY_CHECK=1
# ── Set client-declared model names (the proxy maps them to upstream) ──
export ANTHROPIC_MODEL="$Client_Model_Default"
export ANTHROPIC_DEFAULT_SONNET_MODEL="$Client_Model_Sonnet"
export ANTHROPIC_DEFAULT_OPUS_MODEL="$Client_Model_Opus"
export ANTHROPIC_DEFAULT_HAIKU_MODEL="$Client_Model_Haiku"
export CLAUDE_CODE_SUBAGENT_MODEL="$Client_Model_Haiku"
fi
# ╔══════════════════════════════════════════════════════════════╗
# ║ Launch Claude Code CLI ║
# ╚══════════════════════════════════════════════════════════════╝
echo "[Claude Code] Launching..."
echo ""
npx @anthropic-ai/[email protected]
# ╔══════════════════════════════════════════════════════════════╗
# ║ Cleanup: unset env vars and stop proxy process ║
# ╚══════════════════════════════════════════════════════════════╝
unset ANTHROPIC_BASE_URL ANTHROPIC_API_KEY ANTHROPIC_SKIP_CONNECTIVITY_CHECK CLAUDE_CODE_SKIP_CONNECTIVITY_CHECK
unset ANTHROPIC_MODEL ANTHROPIC_DEFAULT_SONNET_MODEL ANTHROPIC_DEFAULT_OPUS_MODEL ANTHROPIC_DEFAULT_HAIKU_MODEL CLAUDE_CODE_SUBAGENT_MODEL CLAUDE_CODE_EFFORT_LEVEL
unset ANTHROPIC_AUTH_TOKEN
if [[ -n "$PROXY_PID" ]]; then
echo "[Gateway] Stopping proxy process (PID: ${PROXY_PID})..."
kill "${PROXY_PID}" 2>/dev/null
wait "${PROXY_PID}" 2>/dev/null
fi
rm -f "$HOME/.anthropic-proxy.pid"
echo "[Gateway] Environment cleaned up!"
}
Save and exit.
4. Create the Onboarding Bypass Config File
On first login, Claude Code connects to Anthropic and performs a hard country/region check at the physical network layer. You can bypass this by creating a local fake verified-state file:
echo '{"hasCompletedOnboarding": true}' > ~/.claude.json
5. Launch and Test
Reload your zsh configuration (you may need to close and reopen the terminal):
source ~/.zshrc
Type claude directly:
$ claude
[Gateway] Starting protocol conversion proxy...
[Gateway] Started (127.0.0.1:4000)
[Claude Code] Launching...
(Claude Code started successfully, ready...)
Tool Call Verification:
Once inside the Claude Code chat window, ask something that requires reading the environment, for example:
"Please check what files are in my current working directory?"
You'll be surprised to see that it requests file system read permission. After allowing it, Claude Code successfully leverages the Tool Use mechanism we just bidirectionally parsed to invoke underlying OS commands, providing code development, file editing, and command-line execution capabilities just like the official version!
6. Uninstalling
Remove the claude function from ~/.zshrc, then delete the proxy script and Claude Code-related files:
rm ~/anthropic-proxy.mjs # Remove proxy script
rm ~/.anthropic-proxy.log # Remove proxy log
rm ~/.anthropic-proxy.pid # Remove proxy PID file
rm ~/.claude.json # Remove Claude Code config
rm -rf ~/.claude # Remove Claude Code local files
npx clear-npx-cache # Clear all npx cache including @anthropic-ai/[email protected]
7. License
This project is licensed under the MIT License.
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi