| 1 | import Link from "next/link"; |
| 2 | import { Seal } from "@/components/seal"; |
| 3 | import { InstallCodeBlock } from "@/components/install-code-block"; |
| 4 | import { InstallBinary } from "@/components/install-binary"; |
| 5 | import { GETTING_STARTED_STEPS } from "@/lib/content/getting-started"; |
| 6 | import { getFacts } from "@/lib/facts"; |
| 7 | import { buildPageMetadata } from "@/lib/page-meta"; |
| 8 | |
| 9 | export const revalidate = 300; |
| 10 | |
| 11 | export async function generateMetadata({ params }: { params: Promise<{ locale: string }> }) { |
| 12 | const { locale } = await params; |
| 13 | const isZh = locale === "zh"; |
| 14 | return buildPageMetadata({ |
| 15 | path: "/install", |
| 16 | locale, |
| 17 | title: isZh ? "安装 · Codewhale" : "Install · Codewhale", |
| 18 | description: isZh |
| 19 | ? "一行 curl -fsSL https://codewhale.net/install.sh | sh 安装或更新 Codewhale,也支持 npm、Cargo、GitHub Releases、CNB 镜像、Homebrew、预编译二进制、Docker 和源码编译。" |
| 20 | : "Install or update Codewhale with curl -fsSL https://codewhale.net/install.sh | sh, or via npm, cargo, GitHub Releases, the CNB mirror, Homebrew, prebuilt binaries, Docker, or from source.", |
| 21 | }); |
| 22 | } |
| 23 | |
| 24 | const SHELL_INSTALL = `curl -fsSL https://codewhale.net/install.sh | sh`; |
| 25 | const SHELL_INSPECT = `curl -fsSL https://codewhale.net/install.sh`; |
| 26 | const NPM_INSTALL = `npm install -g codewhale`; |
| 27 | const CARGO_INSTALL = `cargo install codewhale-cli --locked |
| 28 | cargo install codewhale-tui --locked`; |
| 29 | const FIRST_RUN = `codewhale`; |
| 30 | const UPDATE = `codewhale update`; |
| 31 | |
| 32 | const RELEASE_DOWNLOAD = `# Download your platform archive: |
| 33 | https://github.com/Hmbown/CodeWhale/releases/latest`; |
| 34 | const cnbInstall = (tag: string) => `cargo install --git https://cnb.cool/codewhale.net/codewhale --tag ${tag} codewhale-cli --locked --force |
| 35 | cargo install --git https://cnb.cool/codewhale.net/codewhale --tag ${tag} codewhale-tui --locked --force`; |
| 36 | const TUNA_CONFIG = `# ~/.cargo/config.toml |
| 37 | [source.crates-io] |
| 38 | replace-with = "tuna" |
| 39 | |
| 40 | [source.tuna] |
| 41 | registry = "sparse+https://mirrors.tuna.tsinghua.edu.cn/crates.io-index/"`; |
| 42 | const TUNA_INSTALL = `cargo install codewhale-cli --locked |
| 43 | cargo install codewhale-tui --locked`; |
| 44 | |
| 45 | const BREW = `brew tap Hmbown/deepseek-tui |
| 46 | brew install deepseek-tui`; |
| 47 | |
| 48 | const DOCKER = `docker volume create codewhale-home |
| 49 | docker run --rm -it \\ |
| 50 | -e DEEPSEEK_API_KEY=$DEEPSEEK_API_KEY \\ |
| 51 | -v codewhale-home:/home/codewhale/.codewhale \\ |
| 52 | -v "$PWD:/workspace" -w /workspace \\ |
| 53 | ghcr.io/hmbown/codewhale:latest`; |
| 54 | |
| 55 | const FROM_SOURCE = `git clone https://github.com/Hmbown/CodeWhale |
| 56 | cd CodeWhale |
| 57 | cargo build --release --locked |
| 58 | |
| 59 | # Install two Cargo packages; together they provide three commands |
| 60 | cargo install --path crates/cli --locked # codewhale + codew |
| 61 | cargo install --path crates/tui --locked # codewhale-tui`; |
| 62 | |
| 63 | const CONFIG_TREE = `$CODEWHALE_HOME/ (default: ~/.codewhale/) |
| 64 | ├── config.toml api keys, model, hooks, profiles |
| 65 | ├── mcp.json MCP server definitions |
| 66 | ├── skills/ user skills (each with SKILL.md) |
| 67 | ├── sessions/ checkpoints + offline queue |
| 68 | ├── tasks/ background task store |
| 69 | └── audit.log best-effort credential / approval / elevation events |
| 70 | |
| 71 | ./.codewhale/ project-scoped config (optional, per-repo)`; |
| 72 | |
| 73 | const CONFIG_TREE_ZH = `$CODEWHALE_HOME/(默认:~/.codewhale/) |
| 74 | ├── config.toml API 密钥、模型、钩子、配置集 |
| 75 | ├── mcp.json MCP 服务器定义 |
| 76 | ├── skills/ 用户技能(每个含 SKILL.md) |
| 77 | ├── sessions/ 检查点 + 离线队列 |
| 78 | ├── tasks/ 后台任务存储 |
| 79 | └── audit.log 尽力写入的凭证 / 审批 / 提权事件 |
| 80 | |
| 81 | ./.codewhale/ 项目级配置(可选,每个仓库)`; |
| 82 | |
| 83 | export default async function InstallPage({ params }: { params: Promise<{ locale: string }> }) { |
| 84 | const { locale } = await params; |
| 85 | const isZh = locale === "zh"; |
| 86 | const facts = await getFacts(); |
| 87 | const publishedRelease = facts.latestPublishedRelease; |
| 88 | const sourceIsPublished = publishedRelease?.version === facts.version; |
| 89 | const firstSession = GETTING_STARTED_STEPS.find((step) => step.id === "first-session")!; |
| 90 | const connectProvider = GETTING_STARTED_STEPS.find((step) => step.id === "connect-provider")!; |
| 91 | const verify = `codewhale --version${ |
| 92 | publishedRelease ? ` # latest published: ${publishedRelease.version}` : "" |
| 93 | } |
| 94 | codewhale doctor`; |
| 95 | |
| 96 | const copyLabel = isZh ? "复制" : "Copy"; |
| 97 | const copiedLabel = isZh ? "已复制 ✓" : "Copied ✓"; |
| 98 | |
| 99 | return ( |
| 100 | <> |
| 101 | {/* ① INSTALL */} |
| 102 | <section className="mx-auto max-w-[1100px] px-6 pt-12 pb-10"> |
| 103 | <div className="flex items-baseline gap-4 mb-3"> |
| 104 | <Seal char="装" /> |
| 105 | <div className="eyebrow">{isZh ? "01 · 安装" : "01 · Install"}</div> |
| 106 | </div> |
| 107 | <h1 className="font-display tracking-crisp mb-6"> |
| 108 | {isZh ? ( |
| 109 | <>安装 <span className="font-cjk text-indigo text-5xl ml-2">Install</span></> |
| 110 | ) : ( |
| 111 | <>Install <span className="font-cjk text-indigo text-5xl ml-2">安装</span></> |
| 112 | )} |
| 113 | </h1> |
| 114 | |
| 115 | <div className="space-y-3"> |
| 116 | <InstallCodeBlock cmd={SHELL_INSTALL} copyLabel={copyLabel} copiedLabel={copiedLabel} /> |
| 117 | <InstallCodeBlock cmd={FIRST_RUN} copyLabel={copyLabel} copiedLabel={copiedLabel} /> |
| 118 | </div> |
| 119 | |
| 120 | <p className="mt-4 text-sm text-ink-soft leading-relaxed max-w-2xl"> |
| 121 | {isZh ? ( |
| 122 | <> |
| 123 | macOS / Linux 安装脚本会从 GitHub Releases 下载经 SHA-256 校验的二进制, |
| 124 | 默认安装到 <code className="inline">~/.local/bin</code>,并安装{" "} |
| 125 | <code className="inline">codewhale</code>、<code className="inline">codew</code> 和{" "} |
| 126 | <code className="inline">codewhale-tui</code>。先审阅脚本可运行{" "} |
| 127 | <code className="inline">{SHELL_INSPECT}</code>。下方「其他安装方式」列出 npm、Cargo、GitHub Releases、 |
| 128 | CNB、国内镜像、Homebrew、预编译二进制和 Docker。 |
| 129 | </> |
| 130 | ) : ( |
| 131 | <> |
| 132 | The macOS / Linux installer downloads SHA-256-verified binaries from GitHub Releases, |
| 133 | installs to <code className="inline">~/.local/bin</code> by default, and exposes{" "} |
| 134 | <code className="inline">codewhale</code>, <code className="inline">codew</code>, and{" "} |
| 135 | <code className="inline">codewhale-tui</code>. To inspect it first, run{" "} |
| 136 | <code className="inline">{SHELL_INSPECT}</code>. See{" "} |
| 137 | <a href="#other-ways" className="body-link">Other ways to install</a> below for |
| 138 | npm, cargo, GitHub Releases, CNB, Homebrew, prebuilt binaries, Docker, or mainland |
| 139 | China mirrors. |
| 140 | </> |
| 141 | )} |
| 142 | </p> |
| 143 | </section> |
| 144 | |
| 145 | {/* ② VERIFY */} |
| 146 | <section className="mx-auto max-w-[1100px] px-6 py-10 hairline-t"> |
| 147 | <div className="flex items-baseline gap-4 mb-5"> |
| 148 | <Seal char="验" /> |
| 149 | <div className="eyebrow">{isZh ? "02 · 验证" : "02 · Verify"}</div> |
| 150 | </div> |
| 151 | |
| 152 | <InstallCodeBlock cmd={verify} copyLabel={copyLabel} copiedLabel={copiedLabel} /> |
| 153 | |
| 154 | <p className="mt-4 text-sm text-ink-soft leading-relaxed max-w-2xl"> |
| 155 | {isZh ? ( |
| 156 | <> |
| 157 | <code className="inline">codewhale doctor</code> 检查 API 密钥、网络、沙箱可用性、 |
| 158 | MCP 服务器,并在终端输出修复建议;需要结构化输出时可加{" "} |
| 159 | <code className="inline">--json</code>。 |
| 160 | </> |
| 161 | ) : ( |
| 162 | <> |
| 163 | <code className="inline">codewhale doctor</code> checks your API key, network, |
| 164 | sandbox availability, and MCP servers, then prints remediation guidance. Add{" "} |
| 165 | <code className="inline">--json</code> when you need structured output. |
| 166 | </> |
| 167 | )} |
| 168 | </p> |
| 169 | </section> |
| 170 | |
| 171 | {/* ③ UPDATE */} |
| 172 | <section className="mx-auto max-w-[1100px] px-6 py-10 hairline-t"> |
| 173 | <div className="flex items-baseline gap-4 mb-5"> |
| 174 | <Seal char="新" /> |
| 175 | <div className="eyebrow">{isZh ? "03 · 更新" : "03 · Update"}</div> |
| 176 | </div> |
| 177 | |
| 178 | <InstallCodeBlock cmd={UPDATE} copyLabel={copyLabel} copiedLabel={copiedLabel} /> |
| 179 | <div className="mt-3"> |
| 180 | <InstallCodeBlock cmd={SHELL_INSTALL} copyLabel={copyLabel} copiedLabel={copiedLabel} /> |
| 181 | </div> |
| 182 | |
| 183 | <p className="mt-4 text-sm text-ink-soft leading-relaxed max-w-2xl"> |
| 184 | {isZh ? ( |
| 185 | <> |
| 186 | 检查 GitHub Releases 是否有新版本并就地替换二进制。 |
| 187 | 通过 <code className="inline">install.sh</code> 安装的用户也可以重跑同一条{" "} |
| 188 | <code className="inline">curl</code> 命令覆盖更新。 |
| 189 | 通过包管理器安装的话,用包管理器升级更稳:npm 安装的运行{" "} |
| 190 | <code className="inline">npm update -g codewhale</code>; |
| 191 | Cargo 安装的重跑两个 package 的 <code className="inline">cargo install</code> 命令并加{" "} |
| 192 | <code className="inline">--force</code>(<code className="inline">codewhale-cli</code> 提供 |
| 193 | <code className="inline">codewhale</code> 与 <code className="inline">codew</code>, |
| 194 | <code className="inline">codewhale-tui</code> 提供同名命令); |
| 195 | 旧版 Homebrew tap 用 <code className="inline">brew upgrade deepseek-tui</code>。 |
| 196 | </> |
| 197 | ) : ( |
| 198 | <> |
| 199 | Checks GitHub Releases for a newer version and replaces the binary in place. If you |
| 200 | installed with <code className="inline">install.sh</code>, re-run the same{" "} |
| 201 | <code className="inline">curl</code> command to overwrite the binaries. |
| 202 | If you installed via a package manager, prefer it instead: npm users run{" "} |
| 203 | <code className="inline">npm update -g codewhale</code>; cargo users re-run the two |
| 204 | package <code className="inline">cargo install</code> commands with{" "} |
| 205 | <code className="inline">--force</code> (<code className="inline">codewhale-cli</code> |
| 206 | provides <code className="inline">codewhale</code> and <code className="inline">codew</code>; |
| 207 | <code className="inline">codewhale-tui</code> provides the command of the same name); |
| 208 | the legacy Homebrew tap updates with{" "} |
| 209 | <code className="inline">brew upgrade deepseek-tui</code>. |
| 210 | </> |
| 211 | )} |
| 212 | </p> |
| 213 | </section> |
| 214 | |
| 215 | {/* ④ FIRST RUN */} |
| 216 | <section className="mx-auto max-w-[1100px] px-6 py-10 hairline-t"> |
| 217 | <div className="flex items-baseline gap-4 mb-5"> |
| 218 | <Seal char="始" /> |
| 219 | <div className="eyebrow">{isZh ? "04 · 首次运行" : "04 · First run"}</div> |
| 220 | </div> |
| 221 | |
| 222 | <ol className="space-y-6 max-w-2xl"> |
| 223 | <li> |
| 224 | <div className="font-display text-lg mb-2"> |
| 225 | {isZh ? `① ${firstSession.title.zh}` : `① ${firstSession.title.en}`} |
| 226 | </div> |
| 227 | <p className="text-sm text-ink-soft leading-relaxed"> |
| 228 | {isZh ? firstSession.body.zh : firstSession.body.en} |
| 229 | </p> |
| 230 | <div className="mt-2"> |
| 231 | <InstallCodeBlock |
| 232 | cmd={firstSession.commands.join("\n")} |
| 233 | copyLabel={copyLabel} |
| 234 | copiedLabel={copiedLabel} |
| 235 | /> |
| 236 | </div> |
| 237 | </li> |
| 238 | |
| 239 | <li> |
| 240 | <div className="font-display text-lg mb-2"> |
| 241 | {isZh ? `② ${connectProvider.title.zh}` : `② ${connectProvider.title.en}`} |
| 242 | </div> |
| 243 | <p className="text-sm text-ink-soft leading-relaxed"> |
| 244 | {isZh ? connectProvider.body.zh : connectProvider.body.en} |
| 245 | </p> |
| 246 | <div className="mt-2"> |
| 247 | <InstallCodeBlock |
| 248 | cmd={connectProvider.commands.join("\n")} |
| 249 | copyLabel={copyLabel} |
| 250 | copiedLabel={copiedLabel} |
| 251 | /> |
| 252 | </div> |
| 253 | <Link |
| 254 | href={`/${locale}${connectProvider.link.href}`} |
| 255 | className="body-link mt-2 inline-block text-sm" |
| 256 | > |
| 257 | {isZh ? connectProvider.link.label.zh : connectProvider.link.label.en} → |
| 258 | </Link> |
| 259 | </li> |
| 260 | |
| 261 | <li> |
| 262 | <div className="font-display text-lg mb-2"> |
| 263 | {isZh ? "③ 在项目目录中运行" : "③ Run it in a project"} |
| 264 | </div> |
| 265 | <InstallCodeBlock cmd={`cd path/to/project\ncodewhale`} copyLabel={copyLabel} copiedLabel={copiedLabel} /> |
| 266 | <p className="mt-3 text-sm text-ink-soft leading-relaxed"> |
| 267 | {isZh ? ( |
| 268 | <> |
| 269 | 新会话使用你选择的默认模式(未修改则为 Act)。输入区空闲时,按{" "} |
| 270 | <kbd className="font-mono text-xs px-1 hairline-t hairline-b hairline-l hairline-r">Tab</kbd>{" "} |
| 271 | 循环 Plan → Act → Operate;按{" "} |
| 272 | <kbd className="font-mono text-xs px-1 hairline-t hairline-b hairline-l hairline-r">Shift+Tab</kbd>{" "} |
| 273 | 循环 Ask → Auto-Review → Full Access 权限姿态。也可以运行{" "} |
| 274 | <code className="inline">/mode</code> 选择模式或运行 <code className="inline">/config</code>{" "} |
| 275 | 查看权限。Plan 始终只读;Full Access 仅应用于你信任的工作区。 |
| 276 | </> |
| 277 | ) : ( |
| 278 | <> |
| 279 | New sessions use your selected default mode (Act unless you changed it). When the composer is idle, press{" "} |
| 280 | <kbd className="font-mono text-xs px-1 hairline-t hairline-b hairline-l hairline-r">Tab</kbd>{" "} |
| 281 | to cycle Plan → Act → Operate; press{" "} |
| 282 | <kbd className="font-mono text-xs px-1 hairline-t hairline-b hairline-l hairline-r">Shift+Tab</kbd>{" "} |
| 283 | to cycle Ask → Auto-Review → Full Access permission postures. You can also run{" "} |
| 284 | <code className="inline">/mode</code> to choose a mode or <code className="inline">/config</code>{" "} |
| 285 | to inspect permissions. Plan stays read-only; use Full Access only in a workspace you trust. |
| 286 | </> |
| 287 | )} |
| 288 | </p> |
| 289 | </li> |
| 290 | </ol> |
| 291 | </section> |
| 292 | |
| 293 | {/* ⑤ OTHER WAYS TO INSTALL */} |
| 294 | <section id="other-ways" className="bg-paper-deep hairline-t hairline-b"> |
| 295 | <div className="mx-auto max-w-[1100px] px-6 py-12"> |
| 296 | <div className="flex items-baseline gap-4 mb-5"> |
| 297 | <Seal char="备" /> |
| 298 | <div className="eyebrow">{isZh ? "05 · 其他安装方式" : "05 · Other ways to install"}</div> |
| 299 | </div> |
| 300 | <h2 className="font-display text-3xl mb-2"> |
| 301 | {isZh ? "其他安装方式" : "Other ways to install"} |
| 302 | </h2> |
| 303 | <p className="text-sm text-ink-soft max-w-2xl mb-4"> |
| 304 | {isZh |
| 305 | ? "如果上面的脚本路径不适合你,请从下面选择匹配你环境的方式。各渠道的命令和打包形式有所不同,说明会明确列出安装内容。" |
| 306 | : "If the script above doesn't fit your setup, choose the channel that matches your environment. Command availability and packaging differ by channel, and each description states exactly what it installs."} |
| 307 | </p> |
| 308 | |
| 309 | <p className="text-sm text-ink-soft max-w-2xl mb-10"> |
| 310 | {publishedRelease |
| 311 | ? isZh |
| 312 | ? `下方的发布命令以 ${publishedRelease.tag} 为准;它是 GitHub 上最新的已发布版本。${sourceIsPublished ? "当前源码与该发布版一致。" : `当前源码候选版为 v${facts.version},发布前不会被安装命令当作正式版本。`}` |
| 313 | : `Release-backed commands below use ${publishedRelease.tag}, the latest version published on GitHub. ${sourceIsPublished ? "The current source matches that release." : `The current source candidate is v${facts.version}; install commands do not advertise it before publication.`}` |
| 314 | : isZh |
| 315 | ? "暂时无法验证最新的 GitHub 发布标签;请先查看 Releases,再运行需要固定标签的命令。" |
| 316 | : "The latest GitHub release tag could not be verified. Check Releases before running a command that requires a pinned tag."} |
| 317 | </p> |
| 318 | |
| 319 | <div className="space-y-10"> |
| 320 | {/* npm */} |
| 321 | <div> |
| 322 | <div className="eyebrow mb-2 text-indigo"> |
| 323 | npm{" "} |
| 324 | <span className="text-ink-mute font-mono normal-case tracking-normal"> |
| 325 | {isZh ? "· Node 18+" : "· Node 18+"} |
| 326 | </span> |
| 327 | </div> |
| 328 | <InstallCodeBlock cmd={NPM_INSTALL} copyLabel={copyLabel} copiedLabel={copiedLabel} /> |
| 329 | <p className="mt-3 text-sm text-ink-soft leading-relaxed max-w-2xl"> |
| 330 | {isZh ? ( |
| 331 | <> |
| 332 | npm wrapper 会从 GitHub Releases 下载经 SHA-256 校验的二进制,并安装{" "} |
| 333 | <code className="inline">codewhale</code>、<code className="inline">codew</code> 和{" "} |
| 334 | <code className="inline">codewhale-tui</code> 三个命令。 |
| 335 | </> |
| 336 | ) : ( |
| 337 | <> |
| 338 | The npm wrapper downloads SHA-256-verified binaries from GitHub Releases and |
| 339 | installs <code className="inline">codewhale</code>,{" "} |
| 340 | <code className="inline">codew</code>, and{" "} |
| 341 | <code className="inline">codewhale-tui</code>. |
| 342 | </> |
| 343 | )} |
| 344 | </p> |
| 345 | </div> |
| 346 | |
| 347 | {/* Cargo */} |
| 348 | <div> |
| 349 | <div className="eyebrow mb-2 text-indigo"> |
| 350 | {isZh ? "Rust 工具链" : "Rust toolchain"} |
| 351 | </div> |
| 352 | <InstallCodeBlock cmd={CARGO_INSTALL} copyLabel={copyLabel} copiedLabel={copiedLabel} /> |
| 353 | <p className="mt-3 text-sm text-ink-soft leading-relaxed max-w-2xl"> |
| 354 | {isZh ? ( |
| 355 | <> |
| 356 | 两个 Cargo package 会把 <code className="inline">codewhale</code>、 |
| 357 | <code className="inline">codew</code> 和 <code className="inline">codewhale-tui</code> |
| 358 | 三个命令安装到 <code className="inline">~/.cargo/bin</code>。 |
| 359 | 需要 Rust 1.88+;Linux 用户先安装 <code className="inline">pkg-config</code> 和{" "} |
| 360 | <code className="inline">libdbus-1-dev</code> 等构建依赖。如未安装 Rust,可访问{" "} |
| 361 | <a href="https://rustup.rs" className="body-link">rustup.rs</a>。 |
| 362 | </> |
| 363 | ) : ( |
| 364 | <> |
| 365 | The two Cargo packages install three commands— |
| 366 | <code className="inline">codewhale</code>, <code className="inline">codew</code>, and{" "} |
| 367 | <code className="inline">codewhale-tui</code>—to <code className="inline">~/.cargo/bin</code>. |
| 368 | Requires Rust 1.88+; install via{" "} |
| 369 | <a href="https://rustup.rs" className="body-link">rustup.rs</a> if you don't have it. |
| 370 | On Linux, install build dependencies such as{" "} |
| 371 | <code className="inline">pkg-config</code> and{" "} |
| 372 | <code className="inline">libdbus-1-dev</code> first. |
| 373 | </> |
| 374 | )} |
| 375 | </p> |
| 376 | </div> |
| 377 | |
| 378 | {/* GitHub Release */} |
| 379 | <div className="rounded-lg border border-ink/12 bg-white/70 p-5"> |
| 380 | <div className="font-display text-lg mb-3">{isZh ? "GitHub Releases" : "GitHub Releases"}</div> |
| 381 | <InstallCodeBlock cmd={RELEASE_DOWNLOAD} copyLabel={copyLabel} copiedLabel={copiedLabel} /> |
| 382 | </div> |
| 383 | |
| 384 | {/* CNB */} |
| 385 | <div className="rounded-lg border border-ink/12 bg-white/70 p-5"> |
| 386 | <div className="font-display text-lg mb-3">{isZh ? "CNB 镜像" : "CNB mirror"}</div> |
| 387 | {publishedRelease ? ( |
| 388 | <InstallCodeBlock |
| 389 | cmd={cnbInstall(publishedRelease.tag)} |
| 390 | copyLabel={copyLabel} |
| 391 | copiedLabel={copiedLabel} |
| 392 | /> |
| 393 | ) : ( |
| 394 | <a |
| 395 | href="https://github.com/Hmbown/CodeWhale/releases/latest" |
| 396 | className="body-link" |
| 397 | > |
| 398 | {isZh ? "查看最新 GitHub 发布" : "Check the latest GitHub release"} |
| 399 | </a> |
| 400 | )} |
| 401 | </div> |
| 402 | |
| 403 | {/* Mainland China network */} |
| 404 | <div> |
| 405 | <div className="eyebrow mb-2 text-indigo"> |
| 406 | {isZh ? "中国大陆网络" : "Mainland China network"} |
| 407 | </div> |
| 408 | <p className="text-sm text-ink-soft leading-relaxed max-w-2xl mb-3"> |
| 409 | {isZh ? ( |
| 410 | <> |
| 411 | <strong className="text-indigo">官方源:</strong> |
| 412 | GitHub Releases 为唯一官方发布源。Cargo 经清华 Tuna 镜像——添加到 <code className="inline">~/.cargo/config.toml</code>: |
| 413 | </> |
| 414 | ) : ( |
| 415 | <> |
| 416 | <strong className="text-indigo">Official source:</strong>{" "} |
| 417 | GitHub Releases is the sole canonical release source. Cargo via Tsinghua Tuna mirror — add to{" "} |
| 418 | <code className="inline">~/.cargo/config.toml</code>: |
| 419 | </> |
| 420 | )} |
| 421 | </p> |
| 422 | <InstallCodeBlock cmd={TUNA_CONFIG} copyLabel={copyLabel} copiedLabel={copiedLabel} /> |
| 423 | <div className="mt-3"> |
| 424 | <InstallCodeBlock cmd={TUNA_INSTALL} copyLabel={copyLabel} copiedLabel={copiedLabel} /> |
| 425 | </div> |
| 426 | |
| 427 | <p className="mt-4 text-sm text-ink-soft leading-relaxed max-w-2xl"> |
| 428 | {isZh ? ( |
| 429 | <> |
| 430 | npm 安装时设置 <code className="inline">CODEWHALE_USE_CNB_MIRROR=1</code>, |
| 431 | wrapper 会改从 CNB 镜像下载二进制而不是 GitHub。Cargo + Tuna 或 CNB |
| 432 | 路径同样可以绕开 GitHub 下载瓶颈。 |
| 433 | DeepSeek API(<code className="inline">api.deepseek.com</code>)在国内直连,无需代理。 |
| 434 | </> |
| 435 | ) : ( |
| 436 | <> |
| 437 | For the npm path, set{" "} |
| 438 | <code className="inline">CODEWHALE_USE_CNB_MIRROR=1</code> and the wrapper |
| 439 | downloads binaries from the CNB mirror instead of GitHub. Cargo + Tuna or the |
| 440 | CNB path also routes around GitHub download bottlenecks. The DeepSeek API at{" "} |
| 441 | <code className="inline">api.deepseek.com</code> is reachable from mainland China |
| 442 | without a proxy. |
| 443 | </> |
| 444 | )} |
| 445 | </p> |
| 446 | </div> |
| 447 | |
| 448 | {/* Homebrew */} |
| 449 | <div> |
| 450 | <div className="eyebrow mb-2 text-indigo"> |
| 451 | Homebrew{" "} |
| 452 | <span className="text-ink-mute font-mono normal-case tracking-normal"> |
| 453 | {isZh ? "· macOS / Linux · 旧版 tap" : "· macOS / Linux · legacy tap"} |
| 454 | </span> |
| 455 | </div> |
| 456 | <InstallCodeBlock cmd={BREW} copyLabel={copyLabel} copiedLabel={copiedLabel} /> |
| 457 | <p className="mt-3 text-sm text-ink-soft leading-relaxed max-w-2xl"> |
| 458 | {isZh |
| 459 | ? "这是旧版 deepseek-tui tap,在 formula 重命名为 codewhale 期间保留以保证兼容,安装的同样是当前版本的二进制。" |
| 460 | : "This is the legacy deepseek-tui tap, kept for compatibility while the formula is renamed to codewhale. It installs the same current-release binaries."} |
| 461 | </p> |
| 462 | </div> |
| 463 | |
| 464 | {/* Prebuilt binary */} |
| 465 | <div> |
| 466 | <div className="eyebrow mb-2 text-indigo"> |
| 467 | {isZh ? "预编译二进制" : "Prebuilt binary"}{" "} |
| 468 | <span className="text-ink-mute font-mono normal-case tracking-normal"> |
| 469 | {isZh ? "· 已自动检测" : "· auto-detected"} |
| 470 | </span> |
| 471 | </div> |
| 472 | <InstallBinary |
| 473 | copyLabel={copyLabel} |
| 474 | copiedLabel={copiedLabel} |
| 475 | verifyHeading={isZh ? "校验 SHA256" : "Verify checksum"} |
| 476 | /> |
| 477 | </div> |
| 478 | |
| 479 | {/* Docker */} |
| 480 | <div> |
| 481 | <div className="eyebrow mb-2 text-indigo">Docker</div> |
| 482 | <InstallCodeBlock cmd={DOCKER} copyLabel={copyLabel} copiedLabel={copiedLabel} /> |
| 483 | <p className="mt-3 text-sm text-ink-soft leading-relaxed max-w-2xl"> |
| 484 | {isZh |
| 485 | ? "发布镜像位于 GHCR。需要固定版本时,把 latest 替换成具体的发布标签。" |
| 486 | : "The release image is published to GHCR. Replace latest with a release tag when you need a pinned version."} |
| 487 | </p> |
| 488 | </div> |
| 489 | |
| 490 | {/* From source */} |
| 491 | <div> |
| 492 | <div className="eyebrow mb-2 text-indigo"> |
| 493 | {isZh ? "从源码编译" : "From source"} |
| 494 | </div> |
| 495 | <InstallCodeBlock cmd={FROM_SOURCE} copyLabel={copyLabel} copiedLabel={copiedLabel} /> |
| 496 | <p className="mt-3 text-sm text-ink-soft leading-relaxed max-w-2xl"> |
| 497 | {isZh |
| 498 | ? "适合本地修改 workspace 或贡献补丁。" |
| 499 | : "Useful for working on the workspace itself or contributing patches."} |
| 500 | </p> |
| 501 | </div> |
| 502 | </div> |
| 503 | </div> |
| 504 | </section> |
| 505 | |
| 506 | {/* ⑥ WHERE CONFIG LIVES */} |
| 507 | <section className="mx-auto max-w-[1100px] px-6 py-12"> |
| 508 | <div className="flex items-baseline gap-4 mb-5"> |
| 509 | <Seal char="件" /> |
| 510 | <div className="eyebrow">{isZh ? "06 · 配置文件在哪" : "06 · Where config lives"}</div> |
| 511 | </div> |
| 512 | <InstallCodeBlock cmd={isZh ? CONFIG_TREE_ZH : CONFIG_TREE} copyLabel={copyLabel} copiedLabel={copiedLabel} /> |
| 513 | <p className="mt-4 text-sm text-ink-soft leading-relaxed max-w-2xl"> |
| 514 | {isZh ? ( |
| 515 | <> |
| 516 | 项目级 <code className="inline">./.codewhale/</code> 目录是可选的——每个仓库可有独立的 MCP 服务器、钩子、 |
| 517 | 技能和配置覆盖(例如提供商密钥)。 |
| 518 | 首次运行时,如果缺少配置文件,系统会询问是否交互式创建。旧版 <code className="inline">~/.deepseek</code> 和 <code className="inline">./.deepseek</code> 路径仍会作为兼容回退读取。 |
| 519 | </> |
| 520 | ) : ( |
| 521 | <> |
| 522 | The project-scoped <code className="inline">./.codewhale/</code> directory is optional — |
| 523 | each repo can carry its own MCP servers, hooks, skills, and config overrides (e.g. |
| 524 | provider keys). On first run the app asks whether to interactively create a config |
| 525 | file if one is missing. Legacy <code className="inline">~/.deepseek</code> and{" "} |
| 526 | <code className="inline">./.deepseek</code> paths are still read as compatibility fallbacks. |
| 527 | </> |
| 528 | )} |
| 529 | </p> |
| 530 | </section> |
| 531 | |
| 532 | {/* ⑦ PROVENANCE */} |
| 533 | <section className="mx-auto max-w-[1100px] px-6 py-12 hairline-t"> |
| 534 | <div className="flex items-baseline gap-4 mb-5"> |
| 535 | <Seal char="源" /> |
| 536 | <div className="eyebrow">{isZh ? "07 · 来源与镜像" : "07 · Provenance & mirrors"}</div> |
| 537 | </div> |
| 538 | |
| 539 | <div className="space-y-4 text-sm text-ink-soft leading-relaxed max-w-2xl"> |
| 540 | <p> |
| 541 | {isZh ? ( |
| 542 | <> |
| 543 | <strong className="text-ink">codewhale.net</strong> 和{" "} |
| 544 | <strong className="text-ink">www.codewhale.net</strong> 是 Codewhale 的官方站点, |
| 545 | 部署在 Cloudflare 上。网站源码位于{" "} |
| 546 | <code className="inline">Hmbown/CodeWhale</code> 仓库的{" "} |
| 547 | <code className="inline">web/</code> 目录下,任何人都可自行部署为镜像。 |
| 548 | </> |
| 549 | ) : ( |
| 550 | <> |
| 551 | <strong className="text-ink">codewhale.net</strong> and{" "} |
| 552 | <strong className="text-ink">www.codewhale.net</strong> are the official Codewhale |
| 553 | sites, deployed on Cloudflare. The website source lives under{" "} |
| 554 | <code className="inline">web/</code> in the{" "} |
| 555 | <code className="inline">Hmbown/CodeWhale</code> repository — anyone can |
| 556 | self-deploy it as a mirror. |
| 557 | </> |
| 558 | )} |
| 559 | </p> |
| 560 | |
| 561 | <div className="grid sm:grid-cols-2 gap-4 mt-4"> |
| 562 | <div> |
| 563 | <div className="eyebrow mb-1 text-indigo">{isZh ? "官方发布" : "Official releases"}</div> |
| 564 | <p> |
| 565 | {isZh |
| 566 | ? "所有正式发布和 SHA-256 校验文件仅通过 GitHub Releases 分发。npm 包从 GitHub Releases 下载经校验的二进制。" |
| 567 | : "All official releases and SHA-256 checksums are distributed exclusively through GitHub Releases. The npm package downloads verified binaries from GitHub Releases."} |
| 568 | </p> |
| 569 | </div> |
| 570 | <div> |
| 571 | <div className="eyebrow mb-1 text-indigo">{isZh ? "CNB 镜像" : "CNB mirror"}</div> |
| 572 | <p> |
| 573 | {isZh ? ( |
| 574 | <> |
| 575 | 面向无法稳定访问 GitHub 的用户,提供 CNB 镜像( |
| 576 | <a href="https://github.com/Hmbown/CodeWhale/blob/main/docs/CNB_MIRROR.md" className="body-link">docs/CNB_MIRROR.md</a> |
| 577 | )。镜像仓库由社区成员维护,发布延迟可能为几小时。 |
| 578 | </> |
| 579 | ) : ( |
| 580 | <> |
| 581 | A CNB mirror is available for users who cannot reliably reach GitHub ( |
| 582 | <a href="https://github.com/Hmbown/CodeWhale/blob/main/docs/CNB_MIRROR.md" className="body-link">docs/CNB_MIRROR.md</a> |
| 583 | ). The mirror is maintained by community members; release latency may be a few hours. |
| 584 | </> |
| 585 | )} |
| 586 | </p> |
| 587 | </div> |
| 588 | <div> |
| 589 | <div className="eyebrow mb-1 text-indigo">{isZh ? "TUNA / 包镜像" : "TUNA / package mirrors"}</div> |
| 590 | <p> |
| 591 | {isZh |
| 592 | ? "Cargo 用户可通过 TUNA(清华大学开源镜像站)加速下载。这些镜像由第三方维护,Codewhale 项目不控制镜像内容。" |
| 593 | : "Cargo users can accelerate downloads via TUNA (Tsinghua University Open Source Mirror). These mirrors are maintained by third parties; the Codewhale project does not control mirror content."} |
| 594 | </p> |
| 595 | </div> |
| 596 | <div> |
| 597 | <div className="eyebrow mb-1 text-indigo">{isZh ? "自行部署" : "Self-deployed"}</div> |
| 598 | <p> |
| 599 | {isZh |
| 600 | ? "自行部署的网站副本、镜像站和第三方包不受 Codewhale 项目控制。请验证下载来源和校验和。" |
| 601 | : "Self-deployed website copies, mirror sites, and third-party packages are not controlled by the Codewhale project. Verify download sources and checksums."} |
| 602 | </p> |
| 603 | </div> |
| 604 | </div> |
| 605 | </div> |
| 606 | </section> |
| 607 | |
| 608 | {/* ⑧ NEXT STEPS */} |
| 609 | <section className="bg-paper-deep hairline-t hairline-b"> |
| 610 | <div className="mx-auto max-w-[1100px] px-6 py-12"> |
| 611 | <div className="flex items-baseline gap-4 mb-5"> |
| 612 | <Seal char="续" /> |
| 613 | <div className="eyebrow">{isZh ? "08 · 下一步" : "08 · Next steps"}</div> |
| 614 | </div> |
| 615 | <div className="grid md:grid-cols-3 gap-0 col-rule hairline-t hairline-b"> |
| 616 | <Link |
| 617 | href={isZh ? "/zh/docs" : "/en/docs"} |
| 618 | className="p-6 hover:bg-paper-deep transition-colors" |
| 619 | > |
| 620 | <div className="font-display text-xl mb-2">Docs</div> |
| 621 | <div className="text-sm text-ink-soft mb-3"> |
| 622 | {isZh ? "模式、工具、配置、提供商、MCP" : "Modes, tools, config, providers, MCP"} |
| 623 | </div> |
| 624 | <span className="font-mono text-[0.7rem] uppercase tracking-widest text-indigo"> |
| 625 | {isZh ? "阅读文档 →" : "Read docs →"} |
| 626 | </span> |
| 627 | </Link> |
| 628 | <Link |
| 629 | href={`/${locale}/faq`} |
| 630 | className="p-6 hover:bg-paper-deep transition-colors" |
| 631 | > |
| 632 | <div className="font-display text-xl mb-2">FAQ</div> |
| 633 | <div className="text-sm text-ink-soft mb-3"> |
| 634 | {isZh ? "安装、配置、模型、提供商等常见问题" : "Common questions on install, config, models, providers"} |
| 635 | </div> |
| 636 | <span className="font-mono text-[0.7rem] uppercase tracking-widest text-indigo"> |
| 637 | {isZh ? "查看 FAQ →" : "See FAQ →"} |
| 638 | </span> |
| 639 | </Link> |
| 640 | <Link |
| 641 | href={`/${locale}/roadmap`} |
| 642 | className="p-6 hover:bg-paper-deep transition-colors" |
| 643 | > |
| 644 | <div className="font-display text-xl mb-2">Roadmap</div> |
| 645 | <div className="text-sm text-ink-soft mb-3"> |
| 646 | {isZh ? "已发布、进行中、考虑中、暂不考虑" : "Shipped, underway, considered, ruled out"} |
| 647 | </div> |
| 648 | <span className="font-mono text-[0.7rem] uppercase tracking-widest text-indigo"> |
| 649 | {isZh ? "查看路线图 →" : "View roadmap →"} |
| 650 | </span> |
| 651 | </Link> |
| 652 | </div> |
| 653 | </div> |
| 654 | </section> |
| 655 | </> |
| 656 | ); |
| 657 | } |
| 658 |