feat: jlink打包脚本 - 创建最小JRE发行版(Windows/Linux/macOS)
- packaging/build-dist.ps1: PowerShell跨平台构建脚本 - packaging/build-dist.sh: Bash构建脚本 - BUILD.md: 完整构建安装指南 - 自动jdeps分析 + jlink精简JRE(~49MB)+ fat jar + 启动脚本 - 发行包约120MB,免安装JDK直接运行 - 删除旧run.bat/run.ps1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -2,6 +2,10 @@
|
|||||||
target/
|
target/
|
||||||
*.class
|
*.class
|
||||||
|
|
||||||
|
# Distribution
|
||||||
|
dist/
|
||||||
|
dist2/
|
||||||
|
|
||||||
# IDE
|
# IDE
|
||||||
.idea/
|
.idea/
|
||||||
*.iml
|
*.iml
|
||||||
|
|||||||
@@ -0,0 +1,269 @@
|
|||||||
|
# Claude Code Java — 构建与安装指南
|
||||||
|
|
||||||
|
## 前置要求
|
||||||
|
|
||||||
|
| 依赖 | 版本 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| **JDK** | 25+ | 必须,推荐 [Oracle JDK 25](https://www.oracle.com/java/technologies/downloads/) 或 [OpenJDK 25](https://jdk.java.net/25/) |
|
||||||
|
| **Maven** | 3.9+ | 必须,[下载地址](https://maven.apache.org/download.cgi) |
|
||||||
|
| **API Key** | - | OpenAI / Anthropic / 兼容 API 的密钥 |
|
||||||
|
|
||||||
|
> ⚠️ JDK 25 是必须的,项目使用了 preview 特性(如 pattern matching、string templates)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 快速开始(开发模式)
|
||||||
|
|
||||||
|
适合开发和调试,通过 Maven 直接运行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 设置 JDK
|
||||||
|
export JAVA_HOME=/path/to/jdk-25 # Linux/macOS
|
||||||
|
set JAVA_HOME=C:\Dev\jdk-25.0.2 # Windows
|
||||||
|
|
||||||
|
# 2. 设置 API Key
|
||||||
|
export AI_API_KEY=your-api-key # Linux/macOS
|
||||||
|
set AI_API_KEY=your-api-key # Windows
|
||||||
|
|
||||||
|
# 3. 运行
|
||||||
|
mvn spring-boot:run
|
||||||
|
```
|
||||||
|
|
||||||
|
> 📌 开发模式下,工作目录(AI 操作的目录)为执行 `mvn` 命令的目录。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 构建发行版(推荐用于日常使用)
|
||||||
|
|
||||||
|
发行版使用 **jlink** 创建精简 JRE,打包为独立可执行程序,无需目标机器安装 JDK。
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
# 构建
|
||||||
|
.\packaging\build-dist.ps1 -JavaHome "C:\Dev\jdk-25.0.2"
|
||||||
|
|
||||||
|
# 或跳过 Maven 构建(已有 jar 的情况)
|
||||||
|
.\packaging\build-dist.ps1 -JavaHome "C:\Dev\jdk-25.0.2" -SkipBuild
|
||||||
|
```
|
||||||
|
|
||||||
|
### Linux / macOS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 构建
|
||||||
|
JAVA_HOME=/path/to/jdk-25 ./packaging/build-dist.sh
|
||||||
|
|
||||||
|
# 或跳过 Maven 构建
|
||||||
|
JAVA_HOME=/path/to/jdk-25 ./packaging/build-dist.sh --skip-build
|
||||||
|
```
|
||||||
|
|
||||||
|
### 构建输出
|
||||||
|
|
||||||
|
```
|
||||||
|
dist/
|
||||||
|
├── bin/
|
||||||
|
│ ├── claude-code # Unix 启动脚本 (Linux/macOS)
|
||||||
|
│ └── claude-code.cmd # Windows 启动脚本
|
||||||
|
├── lib/
|
||||||
|
│ └── claude-code-java.jar # Spring Boot fat jar (~71 MB)
|
||||||
|
└── runtime/ # jlink 精简 JRE (~49 MB)
|
||||||
|
├── bin/
|
||||||
|
├── conf/
|
||||||
|
├── lib/
|
||||||
|
└── release
|
||||||
|
```
|
||||||
|
|
||||||
|
总大小约 **120 MB**(对比完整 JDK ~350 MB)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 安装到系统 PATH
|
||||||
|
|
||||||
|
将 `dist/bin` 加入系统 PATH 后,可在任意目录直接使用 `claude-code` 命令。
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
**方法 1:CMD 临时生效(当前终端)**
|
||||||
|
```cmd
|
||||||
|
set PATH=C:\path\to\claude-code-java\dist\bin;%PATH%
|
||||||
|
```
|
||||||
|
|
||||||
|
**方法 2:PowerShell 临时生效(当前终端)**
|
||||||
|
```powershell
|
||||||
|
$env:PATH = "C:\path\to\claude-code-java\dist\bin;$env:PATH"
|
||||||
|
```
|
||||||
|
|
||||||
|
**方法 3:CMD 永久生效(用户级)**
|
||||||
|
```cmd
|
||||||
|
setx PATH "%PATH%;C:\path\to\claude-code-java\dist\bin"
|
||||||
|
```
|
||||||
|
> 需要重开终端窗口生效。
|
||||||
|
|
||||||
|
**方法 4:PowerShell 永久生效**
|
||||||
|
```powershell
|
||||||
|
$binPath = "C:\path\to\claude-code-java\dist\bin"
|
||||||
|
$currentPath = [Environment]::GetEnvironmentVariable("PATH", "User")
|
||||||
|
if ($currentPath -notmatch [regex]::Escape($binPath)) {
|
||||||
|
[Environment]::SetEnvironmentVariable("PATH", "$currentPath;$binPath", "User")
|
||||||
|
Write-Host "Added to PATH. Restart terminal to take effect."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 临时生效
|
||||||
|
export PATH="/path/to/claude-code-java/dist/bin:$PATH"
|
||||||
|
|
||||||
|
# 永久生效 — 添加到 ~/.bashrc 或 ~/.zshrc
|
||||||
|
echo 'export PATH="/path/to/claude-code-java/dist/bin:$PATH"' >> ~/.bashrc
|
||||||
|
source ~/.bashrc
|
||||||
|
```
|
||||||
|
|
||||||
|
### macOS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 临时生效
|
||||||
|
export PATH="/path/to/claude-code-java/dist/bin:$PATH"
|
||||||
|
|
||||||
|
# 永久生效 — 添加到 ~/.zshrc (macOS 默认 shell 是 zsh)
|
||||||
|
echo 'export PATH="/path/to/claude-code-java/dist/bin:$PATH"' >> ~/.zshrc
|
||||||
|
source ~/.zshrc
|
||||||
|
```
|
||||||
|
|
||||||
|
### 验证安装
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 在任意目录执行
|
||||||
|
claude-code # Linux/macOS
|
||||||
|
claude-code.cmd # Windows CMD
|
||||||
|
claude-code # Windows PowerShell (自动找 .cmd)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 在其他目录使用
|
||||||
|
|
||||||
|
安装到 PATH 后,`claude-code` 可以在任何目录启动。**AI 的工作目录就是你启动命令时的当前目录**。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 示例:在项目目录启动,AI 会自动读取该目录的上下文
|
||||||
|
cd /path/to/my-project
|
||||||
|
claude-code
|
||||||
|
|
||||||
|
# AI 将:
|
||||||
|
# - 自动加载 ./CLAUDE.md(如果存在)
|
||||||
|
# - 读取 .git 信息获取项目上下文
|
||||||
|
# - 所有文件操作基于当前目录
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 示例:在不同项目之间切换
|
||||||
|
cd ~/projects/web-app && claude-code # 操作 web-app 项目
|
||||||
|
cd ~/projects/api-server && claude-code # 操作 api-server 项目
|
||||||
|
```
|
||||||
|
|
||||||
|
### 工作目录说明
|
||||||
|
|
||||||
|
| 场景 | 工作目录 | 说明 |
|
||||||
|
|------|----------|------|
|
||||||
|
| `cd /my-project && claude-code` | `/my-project` | AI 在此目录下操作文件 |
|
||||||
|
| 启动后使用工具 | 当前目录 | `bash`, `file_read` 等都基于启动目录 |
|
||||||
|
| `CLAUDE.md` 加载 | 当前目录 + `~/.claude/` | 项目级 + 全局级自动合并 |
|
||||||
|
| Git 上下文 | 当前目录的 `.git` | 自动检测分支、状态、最近提交 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 环境变量
|
||||||
|
|
||||||
|
| 变量 | 必须 | 说明 | 默认值 |
|
||||||
|
|------|------|------|--------|
|
||||||
|
| `AI_API_KEY` | ✅ | API 密钥 | - |
|
||||||
|
| `CLAUDE_CODE_PROVIDER` | ❌ | 提供者 (`openai` / `anthropic`) | `openai` |
|
||||||
|
| `AI_BASE_URL` | ❌ | API 基础 URL | 按提供者不同 |
|
||||||
|
| `AI_MODEL` | ❌ | 模型名称 | 按提供者不同 |
|
||||||
|
| `AI_MAX_TOKENS` | ❌ | 最大生成 Token 数 | `8096` |
|
||||||
|
| `CLAUDE_CODE_VIM` | ❌ | 启用 Vim 编辑模式 | `0` |
|
||||||
|
| `CLAUDE_CODE_CONTEXT_WINDOW` | ❌ | 上下文窗口大小 | `200000` |
|
||||||
|
|
||||||
|
建议将常用变量配置到 shell profile 中:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# ~/.bashrc 或 ~/.zshrc
|
||||||
|
export AI_API_KEY="sk-your-key-here"
|
||||||
|
export CLAUDE_CODE_PROVIDER="openai"
|
||||||
|
export AI_BASE_URL="https://api.deepseek.com"
|
||||||
|
export AI_MODEL="deepseek-chat"
|
||||||
|
```
|
||||||
|
|
||||||
|
Windows 可用 `setx` 持久化:
|
||||||
|
```cmd
|
||||||
|
setx AI_API_KEY "sk-your-key-here"
|
||||||
|
setx CLAUDE_CODE_PROVIDER "openai"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 跨平台构建注意事项
|
||||||
|
|
||||||
|
jlink 创建的 JRE 是 **平台相关** 的。在 Windows 上构建的 `dist/` 只能在 Windows 上运行。
|
||||||
|
|
||||||
|
如果需要为多个平台构建:
|
||||||
|
|
||||||
|
| 构建平台 | 产出 | 可运行平台 |
|
||||||
|
|----------|------|------------|
|
||||||
|
| Windows x64 | `dist/runtime/` (Windows JRE) | Windows x64 |
|
||||||
|
| Linux x64 | `dist/runtime/` (Linux JRE) | Linux x64 |
|
||||||
|
| macOS ARM | `dist/runtime/` (macOS JRE) | macOS ARM (M1/M2/M3) |
|
||||||
|
| macOS x64 | `dist/runtime/` (macOS JRE) | macOS Intel |
|
||||||
|
|
||||||
|
> 💡 `lib/claude-code-java.jar` 是跨平台的,只有 `runtime/` 需要针对每个平台构建。
|
||||||
|
>
|
||||||
|
> 如果在 CI/CD 中构建,可以在 GitHub Actions 中使用 matrix strategy 分别在 `ubuntu-latest`, `windows-latest`, `macos-latest` 上构建。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### Q: 启动时报 "OpenAI API key must be set"
|
||||||
|
|
||||||
|
设置 `AI_API_KEY` 环境变量:
|
||||||
|
```bash
|
||||||
|
export AI_API_KEY="your-key"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q: Windows 终端中文乱码
|
||||||
|
|
||||||
|
发行版启动脚本已自动执行 `chcp 65001`。如果仍有问题,手动运行:
|
||||||
|
```cmd
|
||||||
|
chcp 65001
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q: 如何使用 Anthropic API 而不是 OpenAI?
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export CLAUDE_CODE_PROVIDER="anthropic"
|
||||||
|
export AI_API_KEY="sk-ant-your-key"
|
||||||
|
export AI_MODEL="claude-sonnet-4-20250514"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q: 如何使用 DeepSeek / Azure OpenAI 等兼容 API?
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export CLAUDE_CODE_PROVIDER="openai"
|
||||||
|
export AI_BASE_URL="https://api.deepseek.com"
|
||||||
|
export AI_MODEL="deepseek-chat"
|
||||||
|
export AI_API_KEY="your-deepseek-key"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Q: dist/ 目录可以复制到其他机器吗?
|
||||||
|
|
||||||
|
可以,只要目标机器的操作系统和 CPU 架构与构建机器一致。`dist/` 是完全自包含的,不需要安装 JDK。
|
||||||
|
|
||||||
|
### Q: 如何更新?
|
||||||
|
|
||||||
|
重新执行构建脚本覆盖 `dist/` 目录即可:
|
||||||
|
```bash
|
||||||
|
git pull
|
||||||
|
./packaging/build-dist.sh # 或 .ps1
|
||||||
|
```
|
||||||
@@ -57,6 +57,8 @@
|
|||||||
|
|
||||||
## 🚀 快速开始
|
## 🚀 快速开始
|
||||||
|
|
||||||
|
> 📖 完整的构建、安装、跨平台使用说明请参阅 **[BUILD.md](BUILD.md)**
|
||||||
|
|
||||||
### 前置要求
|
### 前置要求
|
||||||
|
|
||||||
- **JDK 25**(配置 `JAVA_HOME`)
|
- **JDK 25**(配置 `JAVA_HOME`)
|
||||||
@@ -90,19 +92,20 @@ export AI_MODEL="gpt-4o"
|
|||||||
|
|
||||||
### 运行
|
### 运行
|
||||||
|
|
||||||
**Windows PowerShell:**
|
**构建发行版后运行:**
|
||||||
```powershell
|
```bash
|
||||||
.\run.ps1
|
# 1. 构建发行包(仅需一次)
|
||||||
```
|
.\packaging\build-dist.ps1 -JavaHome "C:\Dev\jdk-25.0.2" # Windows
|
||||||
|
# 或
|
||||||
|
JAVA_HOME=/path/to/jdk-25 ./packaging/build-dist.sh # Linux/macOS
|
||||||
|
|
||||||
**Windows CMD:**
|
# 2. 运行
|
||||||
```cmd
|
dist\bin\claude-code.cmd # Windows
|
||||||
run.bat
|
dist/bin/claude-code # Linux/macOS
|
||||||
```
|
```
|
||||||
|
|
||||||
**手动运行:**
|
**开发模式运行:**
|
||||||
```bash
|
```bash
|
||||||
cd claude-code-copy
|
|
||||||
mvn spring-boot:run
|
mvn spring-boot:run
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -589,11 +592,50 @@ mvn clean package -DskipTests
|
|||||||
java -jar target/claude-code-java-0.1.0-SNAPSHOT.jar
|
java -jar target/claude-code-java-0.1.0-SNAPSHOT.jar
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 发行版构建(jlink 最小 JRE)
|
||||||
|
|
||||||
|
创建包含精简 JRE 的独立发行包,无需目标机器安装 JDK:
|
||||||
|
|
||||||
|
**Windows (PowerShell):**
|
||||||
|
```powershell
|
||||||
|
.\packaging\build-dist.ps1 -JavaHome "C:\Dev\jdk-25.0.2"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Linux / macOS (Bash):**
|
||||||
|
```bash
|
||||||
|
JAVA_HOME=/path/to/jdk-25 ./packaging/build-dist.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
生成的 `dist/` 目录结构:
|
||||||
|
```
|
||||||
|
dist/
|
||||||
|
├── bin/
|
||||||
|
│ ├── claude-code # Unix 启动脚本
|
||||||
|
│ └── claude-code.cmd # Windows 启动脚本
|
||||||
|
├── lib/
|
||||||
|
│ └── claude-code-java.jar # Spring Boot fat jar (~71 MB)
|
||||||
|
└── runtime/ # jlink 精简 JRE (~49 MB)
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
使用方式:
|
||||||
|
```bash
|
||||||
|
# 将 bin/ 加入 PATH
|
||||||
|
export PATH="/path/to/dist/bin:$PATH" # Linux/macOS
|
||||||
|
set PATH=C:\path\to\dist\bin;%PATH% # Windows
|
||||||
|
|
||||||
|
# 设置 API Key 后即可使用
|
||||||
|
export AI_API_KEY=your-key
|
||||||
|
claude-code
|
||||||
|
```
|
||||||
|
|
||||||
|
> 💡 发行包约 120 MB,比完整 JDK(~350 MB)小得多。每个平台需要独立构建(jlink JRE 是平台相关的)。
|
||||||
|
|
||||||
### 已知问题
|
### 已知问题
|
||||||
|
|
||||||
- **Windows 编码**:需要 `chcp 65001` 切换到 UTF-8 编码页(启动脚本已自动处理)
|
- **Windows 编码**:需要 `chcp 65001` 切换到 UTF-8 编码页(发行版启动脚本已自动处理)
|
||||||
- **IDE 终端**:IntelliJ IDEA 等 IDE 内置终端为 dumb 模式,Tab 补全和行编辑受限
|
- **IDE 终端**:IntelliJ IDEA 等 IDE 内置终端为 dumb 模式,Tab 补全和行编辑受限
|
||||||
- **JDK 25 警告**:Maven 的 jansi/guava 会触发 native access 警告(启动脚本已通过 MAVEN_OPTS 抑制)
|
- **JDK 25 警告**:Maven 的 jansi/guava 会触发 native access 警告(启动脚本已通过 JVM 参数抑制)
|
||||||
|
|
||||||
## 📝 对应关系
|
## 📝 对应关系
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,254 @@
|
|||||||
|
#!/usr/bin/env pwsh
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
构建 Claude Code Java 发行版(jlink 最小 JRE + fat jar)
|
||||||
|
.DESCRIPTION
|
||||||
|
生成可分发包:bin/ 启动脚本 + lib/ fat jar + runtime/ 精简 JRE
|
||||||
|
用户只需将 bin/ 目录加入 PATH 即可使用 claude-code 命令
|
||||||
|
.PARAMETER JavaHome
|
||||||
|
JDK 25 安装路径(默认使用 JAVA_HOME 环境变量)
|
||||||
|
.PARAMETER OutputDir
|
||||||
|
输出目录(默认 dist/)
|
||||||
|
.PARAMETER SkipBuild
|
||||||
|
跳过 Maven 构建(使用已存在的 jar)
|
||||||
|
.EXAMPLE
|
||||||
|
.\packaging\build-dist.ps1
|
||||||
|
.\packaging\build-dist.ps1 -JavaHome "C:\Dev\jdk-25.0.2"
|
||||||
|
.\packaging\build-dist.ps1 -SkipBuild
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[string]$JavaHome = $env:JAVA_HOME,
|
||||||
|
[string]$OutputDir = "dist",
|
||||||
|
[switch]$SkipBuild
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
$ProjectRoot = Split-Path -Parent $PSScriptRoot
|
||||||
|
|
||||||
|
# ─── 验证环境 ───
|
||||||
|
$javaExe = if ($IsWindows -or $env:OS -eq "Windows_NT") { "java.exe" } else { "java" }
|
||||||
|
$jlinkExe = if ($IsWindows -or $env:OS -eq "Windows_NT") { "jlink.exe" } else { "jlink" }
|
||||||
|
$jdepsExe = if ($IsWindows -or $env:OS -eq "Windows_NT") { "jdeps.exe" } else { "jdeps" }
|
||||||
|
|
||||||
|
if (-not $JavaHome) {
|
||||||
|
Write-Error "JAVA_HOME not set. Use -JavaHome parameter or set JAVA_HOME environment variable."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
$javaBinPath = Join-Path $JavaHome "bin"
|
||||||
|
if (-not (Test-Path (Join-Path $javaBinPath $javaExe))) {
|
||||||
|
Write-Error "JDK not found at $JavaHome. Ensure JDK 25 is installed."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$env:JAVA_HOME = $JavaHome
|
||||||
|
$env:PATH = "$javaBinPath$([IO.Path]::PathSeparator)$env:PATH"
|
||||||
|
|
||||||
|
$javaVersion = & (Join-Path $javaBinPath $javaExe) --version 2>&1 | Select-Object -First 1
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host " Claude Code Java - Distribution Builder" -ForegroundColor Cyan
|
||||||
|
Write-Host " ========================================" -ForegroundColor Cyan
|
||||||
|
Write-Host " JDK: $javaVersion" -ForegroundColor Gray
|
||||||
|
Write-Host " Output: $OutputDir" -ForegroundColor Gray
|
||||||
|
|
||||||
|
# ─── 检测平台 ───
|
||||||
|
$isWin = $IsWindows -or ($env:OS -eq "Windows_NT")
|
||||||
|
$isMac = $IsMacOS
|
||||||
|
if ($isWin) { $platform = "windows-x64" }
|
||||||
|
elseif ($isMac) {
|
||||||
|
$arch = & uname -m 2>&1
|
||||||
|
$platform = if ($arch -match "arm64") { "macos-aarch64" } else { "macos-x64" }
|
||||||
|
} else {
|
||||||
|
$arch = & uname -m 2>&1
|
||||||
|
$platform = if ($arch -match "aarch64") { "linux-aarch64" } else { "linux-x64" }
|
||||||
|
}
|
||||||
|
Write-Host " Platform: $platform" -ForegroundColor Gray
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
# ─── Step 1: Maven 构建 ───
|
||||||
|
Push-Location $ProjectRoot
|
||||||
|
try {
|
||||||
|
if (-not $SkipBuild) {
|
||||||
|
Write-Host "[1/4] Building fat jar with Maven..." -ForegroundColor Yellow
|
||||||
|
& mvn package -q -DskipTests 2>&1
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Write-Error "Maven build failed"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Write-Host " OK Build succeeded" -ForegroundColor Green
|
||||||
|
} else {
|
||||||
|
Write-Host "[1/4] Skipping build (using existing jar)" -ForegroundColor DarkGray
|
||||||
|
}
|
||||||
|
|
||||||
|
# 查找 fat jar
|
||||||
|
$jarFile = Get-ChildItem "target/*.jar" -ErrorAction SilentlyContinue |
|
||||||
|
Where-Object { $_.Name -notmatch "original" } |
|
||||||
|
Select-Object -First 1
|
||||||
|
if (-not $jarFile) {
|
||||||
|
Write-Error "No jar found in target/. Run without -SkipBuild."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
$jarSize = [math]::Round($jarFile.Length / 1MB, 1)
|
||||||
|
Write-Host " Jar: $($jarFile.Name) ($jarSize MB)" -ForegroundColor Gray
|
||||||
|
|
||||||
|
# ─── Step 2: jdeps 分析模块 ───
|
||||||
|
Write-Host "[2/4] Analyzing module dependencies with jdeps..." -ForegroundColor Yellow
|
||||||
|
$detected = & (Join-Path $javaBinPath $jdepsExe) --print-module-deps --ignore-missing-deps --multi-release 25 $jarFile.FullName 2>&1
|
||||||
|
if ($LASTEXITCODE -ne 0 -or -not $detected) {
|
||||||
|
Write-Host " Warning: jdeps failed, using default modules" -ForegroundColor DarkYellow
|
||||||
|
$detected = "java.base,java.desktop,java.management,java.net.http"
|
||||||
|
}
|
||||||
|
Write-Host " Detected: $detected" -ForegroundColor Gray
|
||||||
|
|
||||||
|
# Spring Boot 运行时必要模块
|
||||||
|
$required = @(
|
||||||
|
"java.naming", # JNDI (Spring)
|
||||||
|
"java.xml", # XML processing (Spring)
|
||||||
|
"java.sql", # JDBC
|
||||||
|
"java.instrument", # Java agent / instrumentation
|
||||||
|
"java.compiler", # Annotation processing
|
||||||
|
"java.scripting", # Script engines
|
||||||
|
"jdk.unsupported", # sun.misc.Unsafe
|
||||||
|
"jdk.crypto.ec", # HTTPS/TLS ECDH
|
||||||
|
"jdk.zipfs", # ZIP filesystem provider
|
||||||
|
"jdk.jfr", # Flight Recorder
|
||||||
|
"jdk.net" # Extended socket options (RestClient)
|
||||||
|
)
|
||||||
|
$allSet = [System.Collections.Generic.HashSet[string]]::new()
|
||||||
|
foreach ($m in ($detected -split ",")) { [void]$allSet.Add($m.Trim()) }
|
||||||
|
foreach ($m in $required) { [void]$allSet.Add($m) }
|
||||||
|
$modules = ($allSet | Sort-Object) -join ","
|
||||||
|
Write-Host " Final modules: $modules" -ForegroundColor Gray
|
||||||
|
|
||||||
|
# ─── Step 3: jlink ───
|
||||||
|
Write-Host "[3/4] Creating minimal JRE with jlink..." -ForegroundColor Yellow
|
||||||
|
$distDir = Join-Path $ProjectRoot $OutputDir
|
||||||
|
$runtimeDir = Join-Path $distDir "runtime"
|
||||||
|
|
||||||
|
if (Test-Path $distDir) { Remove-Item $distDir -Recurse -Force }
|
||||||
|
New-Item -ItemType Directory -Path $distDir -Force | Out-Null
|
||||||
|
|
||||||
|
& (Join-Path $javaBinPath $jlinkExe) `
|
||||||
|
--add-modules $modules `
|
||||||
|
--output $runtimeDir `
|
||||||
|
--strip-debug `
|
||||||
|
--compress zip-6 `
|
||||||
|
--no-header-files `
|
||||||
|
--no-man-pages 2>&1
|
||||||
|
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
Write-Error "jlink failed"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$runtimeSize = [math]::Round(
|
||||||
|
(Get-ChildItem -Recurse $runtimeDir | Measure-Object -Property Length -Sum).Sum / 1MB, 1
|
||||||
|
)
|
||||||
|
Write-Host " OK Runtime: $runtimeSize MB" -ForegroundColor Green
|
||||||
|
|
||||||
|
# ─── Step 4: 组装 ───
|
||||||
|
Write-Host "[4/4] Assembling distribution..." -ForegroundColor Yellow
|
||||||
|
|
||||||
|
# lib/
|
||||||
|
$libDir = Join-Path $distDir "lib"
|
||||||
|
New-Item -ItemType Directory -Path $libDir -Force | Out-Null
|
||||||
|
Copy-Item $jarFile.FullName (Join-Path $libDir "claude-code-java.jar")
|
||||||
|
|
||||||
|
# bin/
|
||||||
|
$binDir = Join-Path $distDir "bin"
|
||||||
|
New-Item -ItemType Directory -Path $binDir -Force | Out-Null
|
||||||
|
|
||||||
|
# ── Windows launcher (claude-code.cmd) ──
|
||||||
|
$cmdContent = @'
|
||||||
|
@echo off
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
chcp 65001 >nul 2>&1
|
||||||
|
|
||||||
|
set "SCRIPT_DIR=%~dp0"
|
||||||
|
set "APP_HOME=%SCRIPT_DIR%.."
|
||||||
|
set "RUNTIME=%APP_HOME%\runtime"
|
||||||
|
set "JAR=%APP_HOME%\lib\claude-code-java.jar"
|
||||||
|
|
||||||
|
if not exist "%RUNTIME%\bin\java.exe" (
|
||||||
|
echo Error: Runtime not found at %RUNTIME%
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
"%RUNTIME%\bin\java.exe" ^
|
||||||
|
--enable-preview ^
|
||||||
|
--enable-native-access=ALL-UNNAMED ^
|
||||||
|
--sun-misc-unsafe-memory-access=allow ^
|
||||||
|
-Xmx512m ^
|
||||||
|
-Djava.net.preferIPv4Stack=true ^
|
||||||
|
-Dstdout.encoding=UTF-8 ^
|
||||||
|
-Dstderr.encoding=UTF-8 ^
|
||||||
|
-Dfile.encoding=UTF-8 ^
|
||||||
|
-jar "%JAR%" ^
|
||||||
|
%*
|
||||||
|
'@
|
||||||
|
Set-Content -Path (Join-Path $binDir "claude-code.cmd") -Value $cmdContent -Encoding ASCII
|
||||||
|
|
||||||
|
# ── Unix launcher (claude-code) ──
|
||||||
|
$shContent = @'
|
||||||
|
#!/bin/sh
|
||||||
|
# Claude Code Java launcher
|
||||||
|
SCRIPT="$0"
|
||||||
|
while [ -L "$SCRIPT" ]; do
|
||||||
|
DIR="$(cd "$(dirname "$SCRIPT")" && pwd)"
|
||||||
|
SCRIPT="$(readlink "$SCRIPT")"
|
||||||
|
[ "${SCRIPT#/}" = "$SCRIPT" ] && SCRIPT="$DIR/$SCRIPT"
|
||||||
|
done
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT")" && pwd)"
|
||||||
|
APP_HOME="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
|
||||||
|
exec "$APP_HOME/runtime/bin/java" \
|
||||||
|
--enable-preview \
|
||||||
|
--enable-native-access=ALL-UNNAMED \
|
||||||
|
--sun-misc-unsafe-memory-access=allow \
|
||||||
|
-Xmx512m \
|
||||||
|
-Djava.net.preferIPv4Stack=true \
|
||||||
|
-Dstdout.encoding=UTF-8 \
|
||||||
|
-Dstderr.encoding=UTF-8 \
|
||||||
|
-Dfile.encoding=UTF-8 \
|
||||||
|
-jar "$APP_HOME/lib/claude-code-java.jar" \
|
||||||
|
"$@"
|
||||||
|
'@
|
||||||
|
$shContent = $shContent -replace "`r`n", "`n"
|
||||||
|
[IO.File]::WriteAllText(
|
||||||
|
(Join-Path $binDir "claude-code"),
|
||||||
|
$shContent,
|
||||||
|
[Text.UTF8Encoding]::new($false)
|
||||||
|
)
|
||||||
|
|
||||||
|
# ── 总计 ──
|
||||||
|
$totalSize = [math]::Round(
|
||||||
|
(Get-ChildItem -Recurse $distDir | Measure-Object -Property Length -Sum).Sum / 1MB, 1
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host " Distribution built successfully!" -ForegroundColor Green
|
||||||
|
Write-Host " ================================" -ForegroundColor Green
|
||||||
|
Write-Host " Location : $distDir" -ForegroundColor White
|
||||||
|
Write-Host " Size : $totalSize MB (Runtime $runtimeSize MB + Jar $jarSize MB)" -ForegroundColor White
|
||||||
|
Write-Host " Platform : $platform" -ForegroundColor White
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host " Quick start:" -ForegroundColor Cyan
|
||||||
|
if ($isWin) {
|
||||||
|
Write-Host " set AI_API_KEY=your-key" -ForegroundColor Gray
|
||||||
|
Write-Host " $binDir\claude-code.cmd" -ForegroundColor Gray
|
||||||
|
} else {
|
||||||
|
Write-Host " chmod +x $binDir/claude-code" -ForegroundColor Gray
|
||||||
|
Write-Host " export AI_API_KEY=your-key" -ForegroundColor Gray
|
||||||
|
Write-Host " $binDir/claude-code" -ForegroundColor Gray
|
||||||
|
}
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host " Or add bin/ to PATH for global access:" -ForegroundColor Cyan
|
||||||
|
if ($isWin) {
|
||||||
|
Write-Host " setx PATH `"%PATH%;$(Resolve-Path $binDir)`"" -ForegroundColor Gray
|
||||||
|
} else {
|
||||||
|
Write-Host " export PATH=`"${binDir}:`$PATH`"" -ForegroundColor Gray
|
||||||
|
}
|
||||||
|
Write-Host ""
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# 构建 Claude Code Java 发行版(jlink 最小 JRE + fat jar)
|
||||||
|
#
|
||||||
|
# 用法:
|
||||||
|
# ./packaging/build-dist.sh # 使用 JAVA_HOME
|
||||||
|
# JAVA_HOME=/path/to/jdk25 ./packaging/build-dist.sh # 指定 JDK
|
||||||
|
# ./packaging/build-dist.sh --skip-build # 跳过 Maven 构建
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
OUTPUT_DIR="${OUTPUT_DIR:-dist}"
|
||||||
|
SKIP_BUILD=false
|
||||||
|
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
--skip-build) SKIP_BUILD=true ;;
|
||||||
|
--help|-h)
|
||||||
|
echo "Usage: $0 [--skip-build]"
|
||||||
|
echo " Environment: JAVA_HOME (required), OUTPUT_DIR (default: dist)"
|
||||||
|
exit 0 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# ─── 验证环境 ───
|
||||||
|
if [ -z "${JAVA_HOME:-}" ] || [ ! -x "$JAVA_HOME/bin/java" ]; then
|
||||||
|
echo "Error: JAVA_HOME not set or JDK not found."
|
||||||
|
echo " export JAVA_HOME=/path/to/jdk-25"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export PATH="$JAVA_HOME/bin:$PATH"
|
||||||
|
JAVA_VERSION=$("$JAVA_HOME/bin/java" --version 2>&1 | head -1)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo " Claude Code Java - Distribution Builder"
|
||||||
|
echo " ========================================"
|
||||||
|
echo " JDK: $JAVA_VERSION"
|
||||||
|
echo " Output: $OUTPUT_DIR"
|
||||||
|
|
||||||
|
# 检测平台
|
||||||
|
OS="$(uname -s)"
|
||||||
|
ARCH="$(uname -m)"
|
||||||
|
case "$OS" in
|
||||||
|
Darwin)
|
||||||
|
PLATFORM="macos-$([ "$ARCH" = "arm64" ] && echo "aarch64" || echo "x64")" ;;
|
||||||
|
Linux)
|
||||||
|
PLATFORM="linux-$([ "$ARCH" = "aarch64" ] && echo "aarch64" || echo "x64")" ;;
|
||||||
|
*)
|
||||||
|
PLATFORM="unknown-$OS-$ARCH" ;;
|
||||||
|
esac
|
||||||
|
echo " Platform: $PLATFORM"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
cd "$PROJECT_ROOT"
|
||||||
|
|
||||||
|
# ─── Step 1: Maven 构建 ───
|
||||||
|
if [ "$SKIP_BUILD" = false ]; then
|
||||||
|
echo "[1/4] Building fat jar with Maven..."
|
||||||
|
mvn package -q -DskipTests
|
||||||
|
echo " OK Build succeeded"
|
||||||
|
else
|
||||||
|
echo "[1/4] Skipping build (using existing jar)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
JAR_FILE=$(find target -maxdepth 1 -name "*.jar" ! -name "*original*" | head -1)
|
||||||
|
if [ -z "$JAR_FILE" ]; then
|
||||||
|
echo "Error: No jar found in target/. Run without --skip-build."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
JAR_SIZE=$(du -m "$JAR_FILE" | cut -f1)
|
||||||
|
echo " Jar: $(basename "$JAR_FILE") (${JAR_SIZE} MB)"
|
||||||
|
|
||||||
|
# ─── Step 2: jdeps 分析 ───
|
||||||
|
echo "[2/4] Analyzing module dependencies with jdeps..."
|
||||||
|
DETECTED=$("$JAVA_HOME/bin/jdeps" --print-module-deps --ignore-missing-deps --multi-release 25 "$JAR_FILE" 2>/dev/null || echo "")
|
||||||
|
if [ -z "$DETECTED" ]; then
|
||||||
|
echo " Warning: jdeps failed, using defaults"
|
||||||
|
DETECTED="java.base,java.desktop,java.management,java.net.http"
|
||||||
|
fi
|
||||||
|
echo " Detected: $DETECTED"
|
||||||
|
|
||||||
|
# 追加 Spring Boot 运行时模块
|
||||||
|
EXTRA="java.naming,java.xml,java.sql,java.instrument,java.compiler,java.scripting,jdk.unsupported,jdk.crypto.ec,jdk.zipfs,jdk.jfr,jdk.net"
|
||||||
|
ALL_MODULES=$(echo "$DETECTED,$EXTRA" | tr ',' '\n' | sort -u | tr '\n' ',' | sed 's/,$//')
|
||||||
|
echo " Final: $ALL_MODULES"
|
||||||
|
|
||||||
|
# ─── Step 3: jlink ───
|
||||||
|
echo "[3/4] Creating minimal JRE with jlink..."
|
||||||
|
DIST_DIR="$PROJECT_ROOT/$OUTPUT_DIR"
|
||||||
|
RUNTIME_DIR="$DIST_DIR/runtime"
|
||||||
|
|
||||||
|
rm -rf "$DIST_DIR"
|
||||||
|
mkdir -p "$DIST_DIR"
|
||||||
|
|
||||||
|
"$JAVA_HOME/bin/jlink" \
|
||||||
|
--add-modules "$ALL_MODULES" \
|
||||||
|
--output "$RUNTIME_DIR" \
|
||||||
|
--strip-debug \
|
||||||
|
--compress zip-6 \
|
||||||
|
--no-header-files \
|
||||||
|
--no-man-pages
|
||||||
|
|
||||||
|
RUNTIME_SIZE=$(du -sm "$RUNTIME_DIR" | cut -f1)
|
||||||
|
echo " OK Runtime: ${RUNTIME_SIZE} MB"
|
||||||
|
|
||||||
|
# ─── Step 4: 组装 ───
|
||||||
|
echo "[4/4] Assembling distribution..."
|
||||||
|
|
||||||
|
# lib/
|
||||||
|
mkdir -p "$DIST_DIR/lib"
|
||||||
|
cp "$JAR_FILE" "$DIST_DIR/lib/claude-code-java.jar"
|
||||||
|
|
||||||
|
# bin/
|
||||||
|
mkdir -p "$DIST_DIR/bin"
|
||||||
|
|
||||||
|
# Unix launcher
|
||||||
|
cat > "$DIST_DIR/bin/claude-code" << 'LAUNCHER'
|
||||||
|
#!/bin/sh
|
||||||
|
SCRIPT="$0"
|
||||||
|
while [ -L "$SCRIPT" ]; do
|
||||||
|
DIR="$(cd "$(dirname "$SCRIPT")" && pwd)"
|
||||||
|
SCRIPT="$(readlink "$SCRIPT")"
|
||||||
|
[ "${SCRIPT#/}" = "$SCRIPT" ] && SCRIPT="$DIR/$SCRIPT"
|
||||||
|
done
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$SCRIPT")" && pwd)"
|
||||||
|
APP_HOME="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
|
||||||
|
exec "$APP_HOME/runtime/bin/java" \
|
||||||
|
--enable-preview \
|
||||||
|
--enable-native-access=ALL-UNNAMED \
|
||||||
|
--sun-misc-unsafe-memory-access=allow \
|
||||||
|
-Xmx512m \
|
||||||
|
-Djava.net.preferIPv4Stack=true \
|
||||||
|
-Dstdout.encoding=UTF-8 \
|
||||||
|
-Dstderr.encoding=UTF-8 \
|
||||||
|
-Dfile.encoding=UTF-8 \
|
||||||
|
-jar "$APP_HOME/lib/claude-code-java.jar" \
|
||||||
|
"$@"
|
||||||
|
LAUNCHER
|
||||||
|
chmod +x "$DIST_DIR/bin/claude-code"
|
||||||
|
|
||||||
|
# Windows launcher
|
||||||
|
cat > "$DIST_DIR/bin/claude-code.cmd" << 'LAUNCHER'
|
||||||
|
@echo off
|
||||||
|
setlocal enabledelayedexpansion
|
||||||
|
chcp 65001 >nul 2>&1
|
||||||
|
set "SCRIPT_DIR=%~dp0"
|
||||||
|
set "APP_HOME=%SCRIPT_DIR%.."
|
||||||
|
"%APP_HOME%\runtime\bin\java.exe" ^
|
||||||
|
--enable-preview ^
|
||||||
|
--enable-native-access=ALL-UNNAMED ^
|
||||||
|
--sun-misc-unsafe-memory-access=allow ^
|
||||||
|
-Xmx512m ^
|
||||||
|
-Djava.net.preferIPv4Stack=true ^
|
||||||
|
-Dstdout.encoding=UTF-8 ^
|
||||||
|
-Dstderr.encoding=UTF-8 ^
|
||||||
|
-Dfile.encoding=UTF-8 ^
|
||||||
|
-jar "%APP_HOME%\lib\claude-code-java.jar" ^
|
||||||
|
%*
|
||||||
|
LAUNCHER
|
||||||
|
|
||||||
|
# 统计
|
||||||
|
TOTAL_SIZE=$(du -sm "$DIST_DIR" | cut -f1)
|
||||||
|
echo ""
|
||||||
|
echo " Distribution built successfully!"
|
||||||
|
echo " ================================"
|
||||||
|
echo " Location : $DIST_DIR"
|
||||||
|
echo " Size : ${TOTAL_SIZE} MB (Runtime ${RUNTIME_SIZE} MB + Jar ${JAR_SIZE} MB)"
|
||||||
|
echo " Platform : $PLATFORM"
|
||||||
|
echo ""
|
||||||
|
echo " Quick start:"
|
||||||
|
echo " export AI_API_KEY=your-key"
|
||||||
|
echo " $DIST_DIR/bin/claude-code"
|
||||||
|
echo ""
|
||||||
|
echo " Or add to PATH:"
|
||||||
|
echo " export PATH=\"$DIST_DIR/bin:\$PATH\""
|
||||||
|
echo ""
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
@echo off
|
|
||||||
REM ============================================
|
|
||||||
REM Claude Code (Java) 启动脚本
|
|
||||||
REM 请在 Windows Terminal / PowerShell / cmd 中运行
|
|
||||||
REM ============================================
|
|
||||||
|
|
||||||
REM === JDK 25 配置 ===
|
|
||||||
set JAVA_HOME=D:\Dev\jdk-25
|
|
||||||
set PATH=%JAVA_HOME%\bin;%PATH%
|
|
||||||
|
|
||||||
REM === 抑制 Maven JVM 的 JDK25 兼容性警告 ===
|
|
||||||
set MAVEN_OPTS=--enable-native-access=ALL-UNNAMED --sun-misc-unsafe-memory-access=allow
|
|
||||||
|
|
||||||
REM === AI API 配置(按需修改) ===
|
|
||||||
REM 选择 API 提供者:openai(默认)或 anthropic
|
|
||||||
REM set CLAUDE_CODE_PROVIDER=openai
|
|
||||||
REM set CLAUDE_CODE_PROVIDER=anthropic
|
|
||||||
|
|
||||||
REM 统一环境变量(两种 Provider 通用)
|
|
||||||
REM set AI_API_KEY=your-api-key-here
|
|
||||||
REM set AI_BASE_URL=https://api.openai.com
|
|
||||||
REM set AI_MODEL=gpt-4o
|
|
||||||
REM
|
|
||||||
REM OpenAI 默认: AI_BASE_URL=https://api.openai.com AI_MODEL=gpt-4o
|
|
||||||
REM Anthropic 默认: AI_BASE_URL=https://api.anthropic.com AI_MODEL=claude-sonnet-4-20250514
|
|
||||||
|
|
||||||
REM === 设置控制台 UTF-8 编码(支持 emoji 等字符) ===
|
|
||||||
chcp 65001 >nul 2>&1
|
|
||||||
|
|
||||||
REM === 启动应用 ===
|
|
||||||
cd /d %~dp0
|
|
||||||
mvn spring-boot:run -q
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
# ============================================
|
|
||||||
# Claude Code (Java) 启动脚本 - PowerShell 版
|
|
||||||
# 请在 Windows Terminal / PowerShell 中运行
|
|
||||||
# ============================================
|
|
||||||
|
|
||||||
# === JDK 25 配置 ===
|
|
||||||
$env:JAVA_HOME = "D:\Dev\jdk-25"
|
|
||||||
$env:Path = "D:\Dev\jdk-25\bin;$env:Path"
|
|
||||||
|
|
||||||
# === 抑制 Maven JVM 的 JDK25 兼容性警告 ===
|
|
||||||
$env:MAVEN_OPTS = "--enable-native-access=ALL-UNNAMED --sun-misc-unsafe-memory-access=allow"
|
|
||||||
|
|
||||||
# === AI API 配置(按需修改) ===
|
|
||||||
# 选择 API 提供者:openai(默认)或 anthropic
|
|
||||||
# $env:CLAUDE_CODE_PROVIDER = "openai" # 使用 OpenAI 兼容 API(支持代理)
|
|
||||||
# $env:CLAUDE_CODE_PROVIDER = "anthropic" # 使用 Anthropic 原生 API
|
|
||||||
|
|
||||||
# 统一环境变量(两种 Provider 通用)
|
|
||||||
# $env:AI_API_KEY = "your-api-key-here" # API 密钥(必须)
|
|
||||||
# $env:AI_BASE_URL = "https://api.openai.com" # API 基础 URL(按 Provider 不同默认值不同)
|
|
||||||
# $env:AI_MODEL = "gpt-4o" # 模型名称(按 Provider 不同默认值不同)
|
|
||||||
#
|
|
||||||
# OpenAI 默认: AI_BASE_URL=https://api.openai.com AI_MODEL=gpt-4o
|
|
||||||
# Anthropic 默认: AI_BASE_URL=https://api.anthropic.com AI_MODEL=claude-sonnet-4-20250514
|
|
||||||
|
|
||||||
# === 设置控制台 UTF-8 编码(支持 emoji 等字符) ===
|
|
||||||
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
|
||||||
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
|
||||||
|
|
||||||
# === 启动应用 ===
|
|
||||||
Set-Location $PSScriptRoot
|
|
||||||
mvn spring-boot:run -q
|
|
||||||
Reference in New Issue
Block a user