返回 CodeWhale
INSTALL.md
根目录 / docs / INSTALL.md
1 # Installing Codewhale
2
3 > 阅读简体中文版:[zh_hans/INSTALL.md](zh_hans/INSTALL.md) (not yet updated for this revision)
4
5 Codewhale is an open-source coding agent that runs in your terminal. You give
6 it a task ("fix the failing test", "add a CLI flag"). It reads your repository,
7 edits files and runs commands. In the default **Ask** posture it applies file
8 edits inside the workspace immediately (and shows you the diff), but asks before
9 running shell commands, so commit or stash anything you care about first. It
10 works with many model providers. **DeepSeek** is the default.
11
12 The command is `codewhale`. `codew` is a shorter alias for the same program.
13
14 This guide was written by installing **v0.10.0** (released 2026-09-22) on a
15 fresh **Ubuntu 24.04 x86_64** machine, on every path described here. Every
16 command shown was run and its output checked (see the [install receipts](https://github.com/codewhale-hq/Codewhale/blob/37ecdfcc49bc68a9b0d058b97c3946e62c34bd31/docs/install-report/v0.10.0-2026-09-23/RECEIPTS.md)). Steps that
17 could not be run on that machine are marked **(untested on this VM: reason)**.
18 macOS, Windows and Android are out of scope, apart from a few notes. A second
19 pass re-ran the installer, manual-download, archive and npm paths, the no-key
20 checks and zsh completion on **macOS 26.1 (Apple silicon)**; see
21 [macOS notes](#macos-notes). Steps that need a model call were not re-run
22 there.
23
24 Install commands that use `latest` resolve to the latest **published** GitHub
25 Release or package. Between releases, `main` may already describe the next
26 version (for example a v0.10.1 source candidate before its tag). A
27 candidate isn't installable until its tag, checksums and release assets
28 exist.
29
30 ---
31
32 ## 60-second quickstart (Linux or macOS)
33
34 ```bash
35 # 1. Install. Downloads two checksum-verified binaries into ~/.local/bin (no sudo).
36 curl -fsSL https://codewhale.net/install.sh | sh
37
38 # 2. Make sure ~/.local/bin is on your PATH, now and in future terminals.
39 echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc # zsh: use ~/.zshrc
40 export PATH="$HOME/.local/bin:$PATH"
41 codewhale --version # -> codewhale 0.10.0 (1be1a703b975)
42
43 # 3. Give it a DeepSeek API key (from https://platform.deepseek.com/api_keys).
44 codewhale auth set --provider deepseek # prompts for the key; nothing is echoed
45 codewhale auth status --provider deepseek # "active source: secret store"
46
47 # 4. Run your first task inside a git repository.
48 cd ~/your-project
49 codewhale
50 ```
51
52 In the TUI, type something concrete:
53
54 ```text
55 create a Python file primes.py that prints the first 10 primes, run it, and show me the output
56 ```
57
58 Codewhale writes the file, shows you a diff, then asks **APPROVAL: bash
59 python3 primes.py – Do you want to proceed?** Press `y` to allow it once. It
60 runs the command and reports the output. Press `Ctrl-D` (with an empty input
61 box) to quit. It prints the command to resume the session later.
62
63 > **If nothing happens after you send your first message,** you have no key
64 > configured. v0.10.0 doesn't warn you in that case. Press **F3**. If DeepSeek
65 > shows `missing key`, press Enter, paste the key, then pick a model and
66 > confirm.
67
68 ---
69
70 ## Contents
71
72 1. [Before you start](#1-before-you-start)
73 2. [Install: recommended installer](#2-recommended-installer-curl--sh)
74 3. [Install: manual download from GitHub Releases](#3-manual-download-from-github-releases)
75 4. [Install: npm](#4-npm)
76 5. [Install: Cargo / build from source](#5-cargo-and-building-from-source)
77 6. [Install: Homebrew (Linux) and Nix](#6-homebrew-on-linux-and-nix)
78 7. [Updating and rolling back](#7-updating-and-rolling-back)
79 8. [API keys and providers](#8-api-keys-and-providers)
80 9. [Shell completions](#9-shell-completions)
81 10. [Running it: TUI, headless, resume](#10-running-it)
82 11. [Terminal notes (Ghostty and others)](#11-terminal-notes)
83 12. [Uninstalling and what Codewhale leaves behind](#12-uninstalling)
84 13. [Troubleshooting](#13-troubleshooting)
85 14. [Appendix: other platforms (not re-tested in this revision)](#appendix-other-platforms-not-re-tested-in-this-revision)
86
87 ---
88
89 ## 1. Before you start
90
91 | You need | Why |
92 |---|---|
93 | Linux x86_64 or arm64, or macOS | Prebuilt binaries exist for these. The Linux binaries are **static** (musl), so they have no glibc or libdbus dependency and run on any distro. |
94 | `curl` (or `wget`) and `sha256sum` (or `shasum`) | The installer uses them to download and verify. |
95 | A model provider key, e.g. [DeepSeek](https://platform.deepseek.com/api_keys) | Codewhale does nothing useful without a model. |
96 | `git` (recommended) | Codewhale works best inside a git repository. |
97 | Optional: Python 3, Node.js 20+ | If present, Codewhale enables its Python and JS execution tools (`codewhale doctor` lists them). |
98
99 **Which install path?**
100
101 * **Most people:** the [recommended installer](#2-recommended-installer-curl--sh).
102 It's the fastest (about 6 s here), verifies checksums, and supports
103 `codewhale update`.
104 * **Air-gapped or security-reviewed machines:**
105 [manual download](#3-manual-download-from-github-releases).
106 * **You already manage CLI tools with npm:** [npm](#4-npm).
107 * **No prebuilt binary for your platform, or you want to build it yourself:**
108 [Cargo](#5-cargo-and-building-from-source).
109
110 Pick **one**. Several installs on one machine end up fighting over PATH (see
111 [Troubleshooting](#13-troubleshooting)).
112
113 **Privacy note:** Codewhale sends aggregate usage counts (PostHog) **by
114 default**. To turn this off permanently:
115 `codewhale config set telemetry false`, or export `CODEWHALE_TELEMETRY=0`,
116 which always wins. The TUI also checks GitHub for updates at startup
117 (`[update] check_for_updates` in `~/.codewhale/config.toml`).
118
119 ---
120
121 <a id="recommended-official-github-releases"></a>
122
123 ## 2. Recommended installer (`curl | sh`)
124
125 **Prerequisites:** curl, `sha256sum` (Linux) or the built-in `shasum` (macOS),
126 a writable home directory. No sudo, no Node, no Rust.
127
128 ```bash
129 curl -fsSL https://codewhale.net/install.sh | sh
130 ```
131
132 What it does (verified):
133
134 * It detects your platform (`linux-x64`, `linux-arm64`, `macos-x64`,
135 `macos-arm64`). It refuses Android/Termux and riscv64 with a clear message.
136 * It downloads `codewhale-<platform>`, `codew-<platform>` and
137 `codewhale-artifacts-sha256.txt` from the latest GitHub Release, and verifies
138 both binaries against the manifest. If either doesn't match, it stops before
139 installing anything (`codewhale install: checksum mismatch for …`).
140 * It installs `~/.local/bin/codewhale` and `~/.local/bin/codew`: two identical
141 78 MB files.
142 * It **never uses sudo and never edits your shell profile.** It refuses to
143 install into system or package-manager directories (`/usr/bin`,
144 `~/.cargo/bin`, Homebrew, `node_modules`, `/nix/store`…) and refuses to
145 overwrite a *different* existing `codewhale`.
146
147 Expected output:
148
149 ```
150 Installing Codewhale for linux-x64
151 Release assets: https://github.com/codewhale-hq/CodeWhale/releases/latest/download
152 Install dir: /home/you/.local/bin
153 Checksums verified
154 Installed checksummed release commands:
155 /home/you/.local/bin/codewhale
156 /home/you/.local/bin/codew
157 …
158 PATH selects no codewhale command; this install is /home/you/.local/bin/codewhale
159 …
160 Put /home/you/.local/bin first on PATH in future shells (run once; this installer does not edit shell profiles):
161 echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
162 Then run: . ~/.bashrc (or open a new terminal)
163 …
164 ```
165
166 ### macOS notes
167
168 Re-checked on macOS 26.1, Apple silicon (`macos-arm64`), with a fresh `HOME`:
169
170 * The installer printed `Installing Codewhale for macos-arm64`, verified
171 checksums with the system tools, and installed `codewhale` and `codew`
172 (64 MiB each, Mach-O arm64) in 4.3 s. Both report
173 `codewhale 0.10.0 (1be1a703b975)`. They ran without a Gatekeeper prompt.
174 * When Node isn't on `PATH`, it also prints `Computer Use is included and needs
175 Node.js 20 or newer on PATH.` The core TUI works without Node, but Computer Use
176 and the JavaScript execution tool (`js_execution`) stay unavailable until Node
177 is on `PATH`.
178 * `codewhale doctor` behaves as on Linux (exit 0, `All checks complete!` with no
179 key, file-based secret store under `~/.codewhale/secrets/`), except that it
180 reports `✓ sandbox available: macos-seatbelt`.
181
182 ### Put it on your PATH
183
184 If the installer says `PATH selects no codewhale command`, `~/.local/bin` isn't
185 on your PATH **in this shell**. The `codewhale.net/install.sh` installer then
186 prints the matching line from the block below for your `$SHELL` (zsh, bash,
187 fish, or a POSIX `sh`; for any other shell, or a directory name with quotes,
188 `$`, backticks or backslashes, it tells you to add the directory yourself). It
189 never edits a shell profile itself. The `install.sh` inside a release archive
190 prints only the current-shell `export` line. On Ubuntu and Debian, `~/.profile` adds
191 `~/.local/bin`, but only if the directory existed when you *logged in*. So:
192
193 * a new SSH or login shell picks it up automatically;
194 * a new terminal **window** on a desktop (GNOME Terminal, Ghostty, …) usually
195 doesn't, until you log out and back in. I hit
196 `bash: codewhale: command not found` in Ghostty right after installing.
197
198 Fix it once:
199
200 ```bash
201 echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc # bash (macOS login bash: ~/.bash_profile, or ~/.profile if only that exists)
202 # echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc # zsh
203 # fish_add_path ~/.local/bin # fish (untested on this VM)
204 export PATH="$HOME/.local/bin:$PATH"; hash -r
205 command -v codewhale codew
206 ```
207
208 ### Options
209
210 ```bash
211 # Choose the directory (must be absolute; created if missing)
212 curl -fsSL https://codewhale.net/install.sh | CODEWHALE_INSTALL_DIR="$HOME/.local/codewhale/bin" sh
213 # Install a specific release
214 curl -fsSL https://codewhale.net/install.sh | CODEWHALE_VERSION=v0.9.13 sh
215 # Show help
216 curl -fsSL https://codewhale.net/install.sh | sh -s -- --help
217 ```
218
219 ### Verify
220
221 ```bash
222 codewhale --version # codewhale 0.10.0 (1be1a703b975)
223 codew --version # same
224 codewhale doctor # diagnostics; see the note in §8 about what it does NOT check
225 ```
226
227 ### Re-running the installer
228
229 * Same version already installed: harmless. It prints
230 `Already installed: …` and exits 0.
231 * Different version already installed: it **refuses**
232 (`codewhale install: refusing to replace existing …/codewhale`), exits 1 and
233 changes nothing. It downloads ~160 MB before refusing. Use
234 [`codewhale update`](#7-updating-and-rolling-back) instead.
235
236 ### Upgrade / uninstall
237
238 * Upgrade: `codewhale update` (see §7).
239 * Uninstall: `rm ~/.local/bin/codewhale ~/.local/bin/codew`, then see §12 for
240 data.
241
242 ---
243
244 ## 3. Manual download from GitHub Releases
245
246 Use this when you want to see and verify every byte yourself. Releases:
247 <https://github.com/codewhale-hq/CodeWhale/releases>. Each platform has **bare
248 binaries** (`codewhale-linux-x64`, `codew-linux-x64`, …) and an **archive**
249 (`codewhale-linux-x64.tar.gz`) that holds the same two binaries plus an
250 `install.sh`.
251
252 ### 3a. Bare binaries
253
254 ```bash
255 mkdir -p ~/codewhale-dl && cd ~/codewhale-dl
256 base=https://github.com/codewhale-hq/CodeWhale/releases/latest/download
257 curl -fsSLO "$base/codewhale-linux-x64" # use linux-arm64 on ARM
258 curl -fsSLO "$base/codew-linux-x64"
259 curl -fsSLO "$base/codewhale-artifacts-sha256.txt"
260 sha256sum -c codewhale-artifacts-sha256.txt --ignore-missing
261 # codew-linux-x64: OK
262 # codewhale-linux-x64: OK
263 mkdir -p ~/.local/bin
264 install -m 755 codewhale-linux-x64 ~/.local/bin/codewhale
265 install -m 755 codew-linux-x64 ~/.local/bin/codew
266 ```
267
268 Then [put `~/.local/bin` on PATH](#put-it-on-your-path) and run
269 `codewhale --version`. On macOS the assets are `codewhale-macos-arm64` and
270 `codew-macos-arm64` (`-macos-x64` on Intel), and the built-in `shasum` verifies
271 them (tested on macOS 26.1, Apple silicon):
272
273 ```bash
274 /usr/bin/shasum -a 256 -c codewhale-artifacts-sha256.txt --ignore-missing
275 # codew-macos-arm64: OK
276 # codewhale-macos-arm64: OK
277 ```
278
279 The `codewhale-macos-arm64.tar.gz` archive verifies the same way against
280 `codewhale-bundles-sha256.txt`, and its `./install.sh` installs into
281 `~/.local/bin` (tested).
282
283 To pin a release, replace `latest/download` with `download/vX.Y.Z`, and take
284 the manifest from the same tag.
285
286 ### 3b. Archive
287
288 ```bash
289 cd "$(mktemp -d)"
290 base=https://github.com/codewhale-hq/CodeWhale/releases/latest/download
291 curl -fsSLO "$base/codewhale-linux-x64.tar.gz"
292 curl -fsSLO "$base/codewhale-bundles-sha256.txt" # note: *bundles*, not *artifacts*
293 sha256sum -c codewhale-bundles-sha256.txt --ignore-missing
294 # codewhale-linux-x64.tar.gz: OK
295 tar -xzf codewhale-linux-x64.tar.gz
296 cd codewhale-linux-x64 && ./install.sh # -> ~/.local/bin; PREFIX=/some/dir ./install.sh -> /some/dir/bin
297 ```
298
299 The archive's `install.sh` behaves like the website installer: no sudo, it
300 leaves differing existing files alone, and it prints the same PATH hint.
301
302 **Upgrade:** `codewhale update` works for both 3a and 3b, because they're
303 "direct binary" installs. **Uninstall:** delete the two files (see §12).
304
305 ---
306
307 ## 4. npm
308
309 **Prerequisites:** Node.js 18+ and npm, with a **global prefix you can write
310 to**. npm installs the registry's latest published version, never an
311 unpublished source candidate.
312
313 ```bash
314 npm install -g codewhale
315 codewhale --version
316 ```
317
318 The package is a small wrapper. Its `postinstall` step downloads the same
319 `codewhale`/`codew` release binaries, checks them against the release's SHA-256
320 manifest, and links `codewhale` and `codew` into npm's global `bin`. The whole
321 thing took 6 s here.
322
323 **Windows npm sessions:** Node remains the native program's launcher for the
324 whole session. A process-name kill such as `taskkill /IM node.exe` or
325 `Get-Process node | Stop-Process -Force` can interrupt this and other npm
326 Codewhale sessions and prevent normal terminal cleanup. Stop only the server
327 PID you started or the process owning its port, or use Codewhale's task
328 cancellation. The Windows
329 native archive/installer avoids this npm-parent dependency; this does not
330 remove Node requirements for optional JavaScript tools. Codewhale's Windows
331 shell safety floor holds recognized image-wide Node kills even in Full Access.
332 An external hard kill or an arbitrary program that terminates the launcher
333 cannot be made graceful by this shell-command check.
334
335 ### If you get `EACCES: permission denied`
336
337 That means Node is installed system-wide (apt, `/usr/local`, `/opt`), and your
338 user can't write to its global prefix:
339
340 ```
341 npm error code EACCES
342 npm error Error: EACCES: permission denied, mkdir '/opt/node22/lib/node_modules/codewhale'
343 ```
344
345 **Don't use `sudo npm`.** Either use a per-user Node (nvm, fnm, volta), or
346 point npm at a directory you own. I tested the second option:
347
348 ```bash
349 npm config set prefix "$HOME/.npm-global"
350 echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.bashrc
351 export PATH="$HOME/.npm-global/bin:$PATH"
352 npm install -g codewhale
353 command -v codewhale codew # ~/.npm-global/bin/codewhale, ~/.npm-global/bin/codew
354 ```
355
356 ### Notes
357
358 * npm hides the download progress. Add `--foreground-scripts` to see it
359 (`codewhale: selected GitHub Releases for v0.10.0 … done.`). The chosen
360 source is also written to
361 `$(npm prefix -g)/lib/node_modules/codewhale/bin/downloads/codewhale.source`.
362 * The package uses 157 MB on disk.
363 * On macOS 26.1 (Apple silicon, Homebrew Node 25) an install into a user-owned
364 prefix (`npm install -g --prefix <dir> codewhale`) took 3 s and linked
365 `codewhale` and `codew`, both `codewhale 0.10.0 (1be1a703b975)`.
366 * **Upgrade:** `npm install -g codewhale@latest`. `codewhale update` refuses
367 on npm installs. It prints migration instructions and exits 1 with
368 `error: The package-managed executable was not changed.`
369 * **Specific version:** `npm install -g codewhale@0.9.13`.
370 * **Uninstall:** `npm uninstall -g codewhale`. This removes only the program,
371 not your data (§12).
372
373 ---
374
375 <a id="4-install-via-cargo-any-tier-1-rust-target"></a><a id="7-build-from-source"></a>
376
377 ## 5. Cargo and building from source
378
379 Use this if there's no prebuilt binary for your platform, or you want to
380 compile it yourself. One Cargo package is required:
381 `codewhale-cli` installs the `codewhale` command. npm and prebuilt releases also
382 expose `codew` as a convenience name for the same compiled runtime; Cargo does
383 not create that alias, so add `alias codew=codewhale` to your shell rc if you
384 want the short name.
385
386 ### Prerequisites (Debian/Ubuntu)
387
388 ```bash
389 sudo apt-get install -y build-essential pkg-config libdbus-1-dev git
390 # Rust via rustup (the distro's cargo is too old for this edition-2024 workspace)
391 curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
392 source "$HOME/.cargo/env"
393 rustc --version # the workspace declares rust-version = 1.89
394 ```
395
396 `libdbus-1-dev` **is required**. Without it the build fails after about a
397 minute with:
398
399 ```
400 error: failed to run custom build command for `libdbus-sys v0.2.7`
401 The system library `dbus-1` required by crate `libdbus-sys` was not found.
402 ```
403
404 Fedora/RHEL: `sudo dnf install -y gcc make pkgconf-pkg-config dbus-devel`
405 **(untested on this VM: Ubuntu only)**.
406
407 ### 5a. From crates.io
408
409 ```bash
410 cargo install codewhale-cli --locked
411 codewhale --version
412 ```
413
414 Tested result: **works**, with current stable Rust (1.98.1).
415 * It took **25 min 31 s** on 4 vCPU and 15 GB RAM, and pulled about 470 MB
416 into `~/.cargo/registry`.
417 * It installs one 122 MB file, `~/.cargo/bin/codewhale`. That's a normal
418 glibc-linked binary, and it needs `libdbus-1` at runtime.
419 * `codewhale --version` prints `codewhale 0.10.0`, with no commit hash.
420 * Headless and TUI smoke tests passed.
421
422 > **v0.10.0 declared "Rust 1.88+", which was wrong.** The workspace now
423 > declares 1.89, the version CI's MSRV job builds. With 1.88.0 the v0.10.0
424 > install fails in seconds:
425 > `rustc 1.88.0 is not supported by the following package: serde-saphyr@1.3.0 requires rustc 1.89`.
426 > Use current stable (`rustup update stable`).
427
428 ### 5b. From a git checkout
429
430 ```bash
431 git clone --depth 1 --branch v0.10.0 https://github.com/codewhale-hq/CodeWhale.git
432 cd CodeWhale
433 cargo install --path crates/cli --locked # installs ~/.cargo/bin/codewhale
434 ```
435
436 Things to know (observed):
437
438 * The repo contains `rust-toolchain.toml` (`channel = "stable"`). The first
439 `cargo` command inside the checkout **silently downloads the latest stable
440 toolchain** (about 250 MB), whatever your default is.
441 * The workspace treats every compiler warning as an error. With Rust 1.89
442 the build **fails** after about 11 minutes with 8
443 `error: this lint expectation is unfulfilled` errors in `codewhale-tui`. Use
444 the stable toolchain the repo selects. Don't pass an older `+toolchain`.
445 * The workspace release profile uses thin LTO. On a 4-vCPU / 15 GB VM, the
446 `codewhale-tui` crate alone compiled for more than an hour, peaking at
447 6–8 GB of RAM. Budget 16 GB or more, and expect this to be the slowest install
448 path by far. `target/` grew past 1.2 GB.
449
450 Tested result: **works** on the repo-selected stable Rust (1.98.1).
451 * `Finished release profile … in 83m 12s`. A Nix build competed for CPU and
452 memory for most of that time, so treat it as an upper bound.
453 * `target/` ended at **3.1 GB**. Delete it afterwards with `cargo clean`.
454 * The binary reports `codewhale 0.10.0 (dev)`, and `exec` worked.
455 * Cargo prints `warning: default toolchain implicitly overridden with
456 stable-x86_64-unknown-linux-gnu by rustup toolchain file`, which is harmless.
457 * **Cargo builds provide no `codew`.**
458
459 **Upgrade:** re-run the same `cargo install … --force` (for crates.io, you can
460 add `--version X.Y.Z`). `codewhale update` refuses Cargo installs.
461 **Uninstall:** `cargo uninstall codewhale-cli`, then §12.
462
463 ---
464
465 ## 6. Homebrew on Linux and Nix
466
467 ### Homebrew on Linux: works, but not with the command the old docs gave
468
469 Prerequisite: Homebrew itself. Its installer needs sudo **once**, to create
470 `/home/linuxbrew/.linuxbrew`. Without sudo rights it stops with
471 `Insufficient permissions to install Homebrew to "/home/linuxbrew/.linuxbrew"`.
472 Ask an admin to run
473 `sudo mkdir -p /home/linuxbrew/.linuxbrew && sudo chown $USER /home/linuxbrew/.linuxbrew`,
474 then re-run the installer. Afterwards, add
475 `eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv bash)"` to `~/.bashrc`,
476 as its "Next steps" say.
477
478 ```bash
479 brew install Hmbown/deepseek-tui/codewhale # full name: taps and trusts in one step
480 ```
481
482 The two-step form (`brew tap Hmbown/deepseek-tui` then `brew install
483 codewhale`) **fails on Homebrew 7.x**:
484
485 ```
486 Error: Refusing to load formula hmbown/deepseek-tui/codewhale from untrusted tap hmbown/deepseek-tui.
487 Run `brew trust --formula hmbown/deepseek-tui/codewhale` or `brew trust hmbown/deepseek-tui` to trust it.
488 ```
489
490 Run `brew trust hmbown/deepseek-tui` first, or use the full name above.
491
492 Tested with Homebrew 7.0.6 against the v0.10.0 tap formula: the install took
493 73 s. The tap formula tracks the latest release and downloads the official
494 release binaries, so there's no compile. It provides **both** `codewhale` and
495 `codew`. The `Hmbown/deepseek-tui` tap formula also depends on `node`, which
496 pulled in 31 bottles (~560 MB) on Linux. That `node` dependency belongs to
497 this tap formula only. The core TUI runs without Node; Computer Use and the JS
498 execution tool use it when it is on PATH.
499
500 * **Upgrade:** `brew upgrade codewhale`. (`codewhale update` refuses, and
501 suggests migrating.)
502 * **Uninstall:** `brew uninstall codewhale && brew untap Hmbown/deepseek-tui`.
503 This also autoremoves the tap's node dependency and anything else it pulled
504 in. Homebrew's
505 download cache (`~/.cache/Homebrew`, ~330 MB) stays until
506 `brew cleanup --prune=all`.
507
508 ### Nix: partially tested
509
510 ```bash
511 # flakes are still experimental; the tested setup enabled them once:
512 mkdir -p ~/.config/nix
513 echo 'experimental-features = nix-command flakes' >> ~/.config/nix/nix.conf
514 nix run github:codewhale-hq/CodeWhale -- --version
515 # one-off alternative (untested on this VM): nix --extra-experimental-features 'nix-command flakes' run github:codewhale-hq/CodeWhale -- --version
516 ```
517
518 Nix 2.35 installed fine; single-user mode needs `/nix` created by root once.
519 Flakes resolved. What I learned before stopping:
520
521 * There's **no binary cache**, so this is a full source build of the
522 **main branch**, not the v0.10.0 release. The binary reports
523 `codewhale 0.10.0 (dev)`.
524 * The build step took 30 min on 4 cores. The package then runs its **test
525 suite** (`doCheck`), which recompiles the workspace in test mode. That took
526 over 70 minutes and more than 8 GB of RAM for one rustc process, and I
527 stopped it at 105 minutes. So `nix run` completing, `nix build`, and
528 `nix profile install/remove` are **(untested on this VM: build did not
529 finish in the time budget; the VM's proxy also required an
530 `--override-input fenix …` workaround)**.
531 * Nix provides only `codewhale`; there's no `codew` (it builds just the
532 `codewhale-cli` package).
533
534 Unless you already live in Nix, use §2 instead.
535
536 ---
537
538 ## 7. Updating and rolling back
539
540 These work for installs from §2 and §3 (direct binaries). Package-manager
541 installs (npm, Cargo, Homebrew) must be updated with their own tool.
542
543 ```bash
544 codewhale update --check
545 # Current binary: /home/you/.local/bin/codewhale
546 # Current version: v0.9.13
547 # Latest stable release: v0.10.0
548 # Update available. Run `/home/you/.local/bin/codewhale update` to install v0.10.0.
549 codewhale update
550 # Downloading codewhale-linux-x64...
551 # SHA256 checksum verified against codewhale-artifacts-sha256.txt from GitHub Releases.
552 # ✅ Successfully updated to v0.10.0!
553 # Updated binaries:
554 # - /home/you/.local/bin/codewhale (codewhale-linux-x64)
555 # - /home/you/.local/bin/codew (codewhale-linux-x64)
556 ```
557
558 It updates `codewhale` **and** `codew` together. It took 10 s here. Run it
559 again and you get `Already up to date; no download needed.` Other options:
560 `--beta` and `--proxy <URL>`.
561
562 <a id="roll-back-to-a-previous-release"></a>
563
564 ### Rolling back (e.g. to v0.9.13)
565
566 `codewhale update` never downgrades, and `CODEWHALE_VERSION=0.9.13 codewhale
567 update` just says "Already up to date". To roll back, replace the files:
568
569 ```bash
570 dir="$(dirname "$(command -v codewhale)")" # the install PATH actually selects
571 rm "$dir/codewhale" "$dir/codew"
572 curl -fsSL https://codewhale.net/install.sh | CODEWHALE_VERSION=v0.9.13 CODEWHALE_INSTALL_DIR="$dir" sh
573 hash -r; codewhale --version # codewhale 0.9.13 (a0b81f619b66)
574 ```
575
576 Tested with both the default `~/.local/bin` and a custom
577 `CODEWHALE_INSTALL_DIR`. Use it only for installer, manual or archive
578 installs. Never point it at an npm, Cargo or Homebrew directory.
579
580 Or keep both versions side by side, and put the old one first on PATH:
581
582 ```bash
583 curl -fsSL https://codewhale.net/install.sh | CODEWHALE_VERSION=v0.9.13 CODEWHALE_INSTALL_DIR="$HOME/.local/codewhale-0.9.13" sh
584 export PATH="$HOME/.local/codewhale-0.9.13:$PATH"; hash -r
585 ```
586
587 To return to the latest after an in-place rollback, run `codewhale update`.
588 (Tested: 0.9.13 → 0.10.0.)
589
590 npm: `npm install -g codewhale@0.9.13`. Cargo:
591 `cargo install codewhale-cli --version 0.9.13 --locked --force` **(untested on
592 this VM: only 0.10.0 was built)**.
593
594 ---
595
596 ## 8. API keys and providers
597
598 ### Where Codewhale looks for a key (first match wins)
599
600 1. `--api-key <KEY>` on the command line
601 2. `api_key` in `~/.codewhale/config.toml`
602 3. the secret store written by `codewhale auth set`
603 4. the environment variable (`DEEPSEEK_API_KEY` for DeepSeek)
604
605 This order matters. **A key in config or the secret store beats
606 `DEEPSEEK_API_KEY`.** If you rotate your key by exporting a new env var, an
607 old stored key keeps being used. I tested this: a wrong key in `config.toml`
608 plus the correct env var gives `Authentication Fails … ****beef is invalid`.
609
610 ### Ways to set a DeepSeek key (all tested)
611
612 **Environment variable.** Good for trying it out and for CI:
613 ```bash
614 export DEEPSEEK_API_KEY=sk-... # add to ~/.bashrc / ~/.zshenv to persist
615 ```
616
617 **`auth set`.** Saves the key for every folder:
618 ```bash
619 codewhale auth set --provider deepseek # prompts: "Enter API key for deepseek:"
620 printf '%s\n' "$KEY" | codewhale auth set --provider deepseek --api-key-stdin # scripted
621 # -> saved API key for deepseek to file-based ("/home/you/.codewhale/secrets/secrets.json") (config contains metadata only)
622 ```
623 The file-based message prints the resolved secret-store path; an explicit
624 `CODEWHALE_HOME` changes that location.
625
626 On Linux, the key is stored in **plaintext** in
627 `~/.codewhale/secrets/secrets.json`, with mode 0600. It is not in an OS
628 keyring. Note that in v0.10.0, `auth set` also writes
629 `default_text_model = "deepseek-v4-pro"` into your config, switching you from
630 the default `deepseek-flash` to the pricier Pro model. Change it back with
631 `/model` in the TUI, or edit `~/.codewhale/config.toml`.
632
633 **Inside the TUI.** Press **F3** (or type `/provider`), select DeepSeek, press
634 Enter, paste the key (masked), pick a model, and confirm. This also writes the
635 secret store, and keeps `deepseek-flash`.
636
637 **Config file.** `~/.codewhale/config.toml`:
638 ```toml
639 [providers.deepseek]
640 api_key = "sk-..."
641 ```
642
643 ### Check which key is active
644
645 ```bash
646 codewhale auth status --provider deepseek
647 # active source: env (last4: ...xxxx) # or: secret store / config / missing
648 # lookup order: config -> secret store -> env
649 codewhale doctor --probe-api
650 # · Testing connection... ✓ API connection successful
651 ```
652
653 Use `auth status`. Plain `codewhale doctor` does **not** tell you: it prints
654 `deepseek: env_source=not inspected` even when the key is set, and it exits 0
655 even when no key is found.
656
657 ### Remove a stored key
658
659 ```bash
660 codewhale auth clear --provider deepseek
661 # cleared API key for deepseek from config and secret store
662 ```
663
664 It doesn't unset `DEEPSEEK_API_KEY` in your shell, and it leaves the
665 `default_text_model` line that `auth set` added.
666
667 ### Other providers
668
669 `codewhale auth list` shows about 50 providers (OpenRouter, Anthropic, OpenAI,
670 Moonshot, Ollama, …). The pattern is the same:
671 `codewhale auth set --provider <name>`, or the provider's env var. Local models
672 (Ollama, vLLM, SGLang) need no key. Only DeepSeek was tested here.
673
674 ---
675
676 <a id="8-shell-completions"></a>
677
678 ## 9. Shell completions
679
680 ```bash
681 # bash (needs the bash-completion package)
682 mkdir -p ~/.local/share/bash-completion/completions
683 codewhale completion bash > ~/.local/share/bash-completion/completions/codewhale
684
685 # zsh
686 mkdir -p ~/.zfunc
687 codewhale completion zsh > ~/.zfunc/_codewhale
688 # in ~/.zshrc, if not already there:
689 # fpath=(~/.zfunc $fpath)
690 # autoload -Uz compinit && compinit
691
692 # fish
693 mkdir -p ~/.config/fish/completions
694 codewhale completion fish > ~/.config/fish/completions/codewhale.fish
695 ```
696
697 Each script registers both `codewhale` and `codew`. `codewhale completions` is
698 an alias. Open a new shell afterwards. Regenerate after upgrading.
699
700 How well they work in v0.10.0 (tested interactively):
701
702 * **bash:** fully works (`codewhale comp<Tab>`, `codew auth <Tab><Tab>`).
703 * **fish:** sub-commands complete with descriptions, but
704 `codewhale completion <Tab>` offers files instead of shell names.
705 * **zsh:** only the first word completes. After a sub-command
706 (`codewhale auth <Tab>`), zsh wrongly lists the top-level commands again
707 (same on macOS zsh 5.9, where it offers all 126 top-level entries).
708
709 PowerShell and Elvish scripts are generated too **(untested on this VM: shells
710 not installed)**.
711
712 ---
713
714 ## 10. Running it
715
716 ### The TUI
717
718 ```bash
719 cd your-git-repo
720 codewhale
721 ```
722
723 * The composer is at the bottom. The footer shows the permission posture
724 (`ask`), the mode (`work`) and the model (`DeepSeek · deepseek-flash`).
725 * **Shift+Tab** cycles the permission posture: Ask → Auto-Review → Full Access.
726 **Tab** (with an empty composer) cycles the mode: Plan → Work → Operate.
727 * In **Ask**, file edits in the workspace are applied and shown as a diff.
728 Shell commands stop at an **APPROVAL** prompt: `y` allow once, `a` allow for
729 this session, `n` deny, `Esc` abort the turn.
730 * Useful keys: **F1** help (or `/help`), **Ctrl-K** command palette, **F3**
731 provider/model picker, **Ctrl-R** resume a past session, **Ctrl-U** clear the
732 input (**Ctrl-Z** restores it), **Ctrl-C** cancel or quit, **Ctrl-D** quit
733 with an empty input. Full list: [KEYBINDINGS.md](KEYBINDINGS.md).
734 * On exit it prints `To resume this session, run codewhale resume <id>`.
735
736 Codewhale creates a `.codewhale/` directory in your repo. Ignore its contents
737 but keep the committable `constitution.json` (these are the same patterns
738 `/init` writes):
739
740 ```gitignore
741 **/.codewhale/*
742 !**/.codewhale/constitution.json
743 ```
744
745 ### Headless (scripts, CI)
746
747 ```bash
748 codewhale exec "Reply with exactly: pong" # one-shot answer, no tools
749 codewhale exec --auto "create primes.py that prints the first 10 primes and run it" # tools, auto-approved
750 codewhale exec --json "…" # summary JSON (provider, model, usage, output)
751 codewhale exec --auto --output-format stream-json "…" # one JSON event per line
752 ```
753
754 `--auto` auto-approves shell commands, so use it only in a repo or sandbox you
755 trust.
756
757 Plain `exec` offers the model no tools. Only `--auto`, `--yolo`,
758 `--allowed-tools` or resuming a session opens a tool surface; limits such as
759 `--max-turns`, `--disallowed-tools`, `--sandbox` and the output format never
760 add tools (tool-only flags print a warning). If the provider stops a reply at
761 its output limit, the model is asked to continue and the printed answer is the
762 whole reply. A plain run takes at most 8 model steps unless `--max-turns` sets
763 another limit; a reply still cut off at that limit fails the run.
764
765 ### Resuming
766
767 ```bash
768 codewhale resume <session-id> # or a unique prefix, e.g. e2525dfb
769 codewhale -c # continue the most recent session in this folder
770 codewhale sessions # list saved sessions
771 codewhale exec --continue "…" # headless follow-up to the latest session
772 codewhale exec --resume <id> "…"
773 ```
774
775 In v0.10.0, only **TUI sessions** and **`--output-format stream-json`** exec
776 runs are saved. A plain `codewhale exec`/`exec --auto` run is *not* saved, so a
777 following `exec --continue` fails with `No saved sessions found for workspace`.
778
779 ---
780
781 ## 11. Terminal notes
782
783 ### Ghostty (tested: Ghostty 1.3.1 on Linux/X11)
784
785 Everything I checked worked in Ghostty with its default config
786 (`TERM=xterm-ghostty`, `COLORTERM=truecolor`). Screenshots are kept with the
787 [install receipts](https://github.com/codewhale-hq/Codewhale/tree/37ecdfcc49bc68a9b0d058b97c3946e62c34bd31/docs/install-report/v0.10.0-2026-09-23/screenshots).
788
789 | Check | Result |
790 |---|---|
791 | Colours / truecolor gradient, box drawing, Unicode (✓ é 日本語) | ✅ |
792 | Window resize (1504×886 → 800×500 → back) reflows cleanly | ✅ |
793 | Mouse wheel scrolls the transcript, with a jump-to-bottom button | ✅ |
794 | Paste (`Ctrl+Shift+V`), multi-line: inserted, not sent | ✅ |
795 | F1, F3, Ctrl-K, Ctrl-R, Tab, Shift+Tab, Ctrl-U/Ctrl-Z, Ctrl-C, Ctrl-D | ✅ |
796 | Window title shows state (`waiting on you…`, `✓ done`) | ✅ |
797 | Exit restores the terminal (normal screen, cursor, no mouse-reporting garbage) | ✅ |
798
799 Ghostty on Linux starts a **non-login** shell, so it reads `~/.bashrc` and not
800 `~/.profile`. That's why you need the PATH line in `~/.bashrc` (§2).
801
802 You may notice small dots and a faint label (e.g. `other · drift`) drifting
803 across empty space after a turn. That's Codewhale's decorative "ambient life"
804 whale, not a rendering bug.
805
806 ### Other terminals
807
808 tmux eats **F1**, so use `/help` there. Some key chords (Ctrl-Shift-…, Ctrl-Tab)
809 need a terminal with an enhanced keyboard protocol; [KEYBINDINGS.md](KEYBINDINGS.md) lists
810 portable alternatives. Windows users should use Windows Terminal
811 **(untested on this VM)**.
812
813 ---
814
815 ## 12. Uninstalling
816
817 ### Step 1: forget stored keys (if you used `auth set` or F3)
818
819 ```bash
820 codewhale auth clear --provider deepseek
821 ```
822
823 ### Step 2: remove the program
824
825 | Installed with | Remove with |
826 |---|---|
827 | installer (§2) or manual (§3) | `rm ~/.local/bin/codewhale ~/.local/bin/codew` (or your `CODEWHALE_INSTALL_DIR`) |
828 | npm | `npm uninstall -g codewhale` |
829 | Cargo | `cargo uninstall codewhale-cli` |
830 | Homebrew | `brew uninstall codewhale && brew untap Hmbown/deepseek-tui` (also removes its node dependency) |
831
832 ### Step 3: remove data. No uninstaller does this for you.
833
834 | Path | What it is | Size seen |
835 |---|---|---|
836 | `~/.codewhale/` | config.toml, **secrets/secrets.json (plaintext keys)**, sessions/, logs/, catalog/ (model list, ~5 MB), skills/, builtin-plugins/, tasks/, automations/, crashes/, audit.log, composer history | 6–7 MB |
837 | `~/.deepseek/snapshots/` | v0.10.0 stores its per-turn **copies of your workspaces** here (a legacy path). Contains the contents of every repo you ran it in. | 0.2–0.6 MB here; grows with repo size |
838 | `<every repo you used>/.codewhale/` | per-workspace state/lock dir | tiny |
839 | completion files | `~/.local/share/bash-completion/completions/codewhale`, `~/.zfunc/_codewhale`, `~/.config/fish/completions/codewhale.fish` | – |
840 | PATH lines you added | `~/.bashrc`, `~/.zshrc`, `~/.profile` | – |
841
842 ```bash
843 rm -rf ~/.codewhale ~/.deepseek/snapshots
844 rmdir ~/.deepseek 2>/dev/null # removes the parent only if it is now empty
845 # per-repo dirs, e.g.:
846 find ~ -type d -name .codewhale -prune -print # review, then delete the ones you want
847 ```
848
849 Codewhale wrote nothing outside `$HOME` and the repos it was used in: no
850 system files, services or cron jobs. (I checked every file owned by the test
851 users outside their home directories.) The commands above delete only
852 `~/.deepseek/snapshots`. If you still use the older DeepSeek-TUI, the rest of
853 `~/.deepseek` (its config and sessions) is left alone.
854
855 ---
856
857 ## 13. Troubleshooting
858
859 Every error below was hit while writing this guide.
860
861 **`bash: codewhale: command not found` right after installing.**
862 `~/.local/bin` isn't on PATH in this terminal. See
863 [Put it on your PATH](#put-it-on-your-path).
864
865 **`npm error code EACCES … permission denied, mkdir '…/lib/node_modules/codewhale'`.**
866 Your Node is system-owned. See [§4](#if-you-get-eacces-permission-denied).
867 Don't use sudo.
868
869 **`error: DeepSeek API key not found.` (from `codewhale exec`)**
870 No key anywhere. Follow the printed steps, or see §8.
871
872 **The TUI shows your message but never answers.**
873 No key (v0.10.0 doesn't say so). Press F3 → DeepSeek → Enter → paste the key.
874
875 **`error: Responses API request failed … Authentication Fails, Your api key: ****dead is invalid`.**
876 The key is wrong or revoked. Run `codewhale auth status --provider deepseek`
877 to see *which* source is being used. Remember that config and the secret store
878 beat the env var. Fix with `codewhale auth set --provider deepseek`, or
879 `codewhale auth clear --provider deepseek` to fall back to the env var. In the
880 TUI, a bad key sends you to a "Choose your model provider" screen that marks
881 DeepSeek `last check failed (authentication)`.
882
883 **`error: Network error: SSE stream request failed after HTTP/1.1 fallback: Responses API request failed. … on Windows or proxy networks, try CODEWHALE_FORCE_HTTP1=1 …`.**
884 Despite the wording, on Linux this usually just means **no connection to
885 `api.deepseek.com`**. Check with `curl -sI https://api.deepseek.com` (a `401`
886 response is fine; it means the host is reachable). If you're behind a proxy,
887 make sure `HTTPS_PROXY` is exported. `codewhale doctor --probe-api` only says
888 `✗ API connection failed` for both bad keys and network problems.
889
890 **`codewhale install: refusing to replace existing ~/.local/bin/codewhale`.**
891 A different version is already installed there. Run `codewhale update`, or
892 delete the two files first (§7 rollback), or install into a fresh
893 `CODEWHALE_INSTALL_DIR`.
894
895 **`codewhale install: checksum mismatch for codew-linux-x64`.**
896 The download was corrupted or tampered with. Nothing was installed. Retry, and
897 if it repeats, don't use a mirror.
898
899 **`error: The package-managed executable was not changed.` (from `codewhale update`)**
900 You installed with npm, Cargo or Homebrew. Update with that tool instead.
901
902 **`error: failed to run custom build command for libdbus-sys` (Cargo).**
903 Run `sudo apt-get install -y libdbus-1-dev pkg-config`.
904
905 **`error: No saved sessions found for workspace …` (from `exec --continue`).**
906 The previous run was plain-text `exec`, which isn't saved. Use the TUI, or
907 `--output-format stream-json`.
908
909 **zsh completion suggests the wrong things after the first word.**
910 Known v0.10.0 bug. bash and fish are fine.
911
912 **Getting help:** `codewhale doctor --json` produces a diagnostics bundle
913 without secrets.
914
915 ---
916
917 ## Appendix: other platforms (not re-tested in this revision)
918
919 The sections below are carried over unchanged from the previous revision of
920 this page. They were **not re-run** for the v0.10.0 install test above
921 (out of scope: Windows, macOS, Android/Termux, FreeBSD, mainland-China
922 mirrors), apart from the macOS paths noted in [macOS notes](#macos-notes).
923 Known contradictions with the published v0.10.0 assets, found by inspecting
924 them ([details](https://github.com/codewhale-hq/Codewhale/blob/37ecdfcc49bc68a9b0d058b97c3946e62c34bd31/docs/install-report/v0.10.0-2026-09-23/DOC_DEFECTS.md), D15 and D16):
925
926 * The winget manifest kept in `packaging/winget/` is stale (0.9.6) and not the
927 published package; winget serves `HunterBown.CodeWhale`, see
928 [Windows winget](#windows-winget).
929 * v0.10.0 publishes both `codewhale-windows-x64.zip` (with an `install.bat`
930 that copies to `%USERPROFILE%\bin`) and `codewhale-windows-x64-portable.zip`;
931 the sections below mention only the first.
932 * The standalone `codewhale.bat` launcher works only next to the x64 exe.
933
934 ### Supported platforms and assets
935
936 The [latest stable release](https://github.com/codewhale-hq/CodeWhale/releases/latest)
937 publishes Linux x64/arm64, macOS x64/arm64, Windows x64/arm64, and Android arm64
938 assets. Artifact presence is distinct from platform qualification.
939 The table below describes the current source tree's platform and secondary
940 packaging support; `latest` installation still selects the published release.
941 Android/Termux is preview pending real-device QA. Linux ARM64 is available from
942 v0.8.8 onward. Linux RISC-V prebuilts are temporarily paused because the locked
943 `rquickjs-sys` dependency does not ship `riscv64gc-unknown-linux-gnu` bindings.
944
945 | Platform | Architecture | GitHub release asset | npm install | `cargo install` |
946 | ------------ | ------------ | ----------------------------------------------------- | :---------: | :-------------: |
947 | Linux | x64 (x86_64) | `codewhale-linux-x64`, `codew-linux-x64` | ✅ | ✅ |
948 | Linux | arm64 | `codewhale-linux-arm64`, `codew-linux-arm64` | ✅ | ✅ |
949 | Android / Termux | arm64 (aarch64) | `codewhale-android-arm64.tar.gz` (published in v0.9.12; device support is preview) | ⚠️⁴ preview | ⚠️⁴ preview |
950 | Linux | riscv64 | temporarily unsupported until upstream bindings land | ❌¹ | ❌³ |
951 | macOS | x64 | `codewhale-macos-x64`, `codew-macos-x64` | ✅ | ✅ |
952 | macOS | arm64 (M-series) | `codewhale-macos-arm64`, `codew-macos-arm64` | ✅ | ✅ |
953 | Windows | x64 | `codewhale-windows-x64.exe`, `codew-windows-x64.exe` | ✅ | ✅ |
954 | Windows | arm64 | `codewhale-windows-arm64.exe`, `codew-windows-arm64.exe` | ✅ | ✅ |
955 | Linux x64 or arm64 on musl (Alpine) | native arch | matching static Linux asset | ✅ (static) | ✅ |
956 | Other Linux (musl on other arches) | — | build from source | ❌¹ | ✅² |
957 | FreeBSD 14+ / OpenBSD | x64, arm64 | `cargo install codewhale-cli --locked` (no prebuilt; see § FreeBSD) | ❌ | ✅² |
958
959 ¹ The npm package will exit with a clear error and point you here.
960 ² Provided your toolchain can compile a recent Rust workspace; see
961 [Build from source](#5-cargo-and-building-from-source) below.
962 ³ RISC-V source builds currently need upstream `rquickjs-sys` RISC-V bindings or
963 a bindgen-enabled dependency build.
964 ⁴ The current npm wrapper recognizes Android arm64 and resolves
965 the matching `codewhale` and `codew` Android assets. npm
966 installation works only for a package version whose GitHub Release publishes
967 those matching assets. The Android/Termux path remains preview-only until the
968 real-device compile, startup, approval, file-tool, and update checks tracked
969 in #4236 and #4242 are complete.
970
971 Android / Termux is not the same target as Linux arm64. Do not install the
972 Linux `codewhale-linux-arm64` archive in Termux; use the Termux-specific
973 Android archive when a release or release candidate publishes one, or build
974 from source inside Termux.
975
976 The current Linux **x64 and arm64** assets are **static musl builds**.
977 The x64 release path has used musl since v0.8.65; v0.9.6 extends the same build
978 and static-launch check to arm64. These binaries have no glibc dependency and
979 run on their matching architecture across Ubuntu, Debian, RHEL/CentOS, and
980 Alpine/musl. SQLite is bundled through `rusqlite`, so no separate `libsqlite3`
981 runtime package is needed.
982
983 #### Linux ARM64 portability
984
985 Linux arm64 assets before v0.9.6 were GNU libc builds and could inherit the
986 Ubuntu 24.04 build host's `GLIBC_2.39` floor. Ubuntu 22.04 ships glibc 2.35, so
987 those older arm64 binaries can fail with errors such as:
988
989 ```text
990 version `GLIBC_2.39' not found
991 ```
992
993 The npm wrapper, `codewhale update`, and the Unix archive installer retain their
994 GNU-binary preflight for older releases. The current arm64 build instead uses
995 `aarch64-unknown-linux-musl`, so it has no `GLIBC_*` floor. If you are installing
996 an earlier release on an older arm64 distribution, use:
997
998 ```bash
999 cargo install codewhale-cli --locked # installs `codewhale`
1000 ```
1001
1002 > **Linux ARM64 note (v0.8.7 and earlier).** v0.8.7 and earlier do **not**
1003 > publish a Linux ARM64 prebuilt; users on HarmonyOS thin-and-light, Asahi
1004 > Linux, Raspberry Pi, AWS Graviton, etc. saw `Unsupported architecture: arm64`
1005 > from `npm i -g codewhale`. v0.8.8 publishes `codewhale-linux-arm64`, so a plain `npm i -g codewhale` works
1006 > on any glibc-based ARM64 Linux. If you're stuck on v0.8.7, jump to
1007 > [Build from source](#5-cargo-and-building-from-source) — `cargo install` works fine.
1008 > For HarmonyOS PC and OpenHarmony cross-build setup, see
1009 > [HarmonyOS and OpenHarmony](HarmonyOS.md).
1010
1011 ### Migrating from npm, Cargo, or another installation
1012
1013 #### Migrating from npm, Cargo, or another installation
1014
1015 Package managers continue to own their files. `codewhale update` gives migration
1016 instructions for npm, Cargo, Homebrew, and Omarchy instead of overwriting them.
1017 Known system/package directories are also protected. A `CODEWHALE_INSTALL_METHOD=binary`
1018 override cannot bypass a recognized managed path.
1019
1020 Create a fresh destination when `~/.local/bin` is occupied or a sibling command
1021 has different bytes. This leaves every existing installation in place:
1022
1023 ```bash
1024 mkdir -p "$HOME/.local"
1025 codewhale_install_dir="$(mktemp -d "$HOME/.local/codewhale-release.XXXXXX")"
1026 curl -fsSL https://codewhale.net/install.sh | CODEWHALE_INSTALL_DIR="$codewhale_install_dir" sh
1027 "$codewhale_install_dir/codewhale" --version
1028 export PATH="$codewhale_install_dir:$PATH"
1029 hash -r
1030 command -v codewhale codew
1031 "$codewhale_install_dir/codewhale" update --check
1032 ```
1033
1034 After verifying the version and command paths, keep that directory first in your
1035 shell profile. In PowerShell, use `Get-Command codewhale, codew -All` to inspect
1036 resolution; run the selected executable using its full path. A successful update
1037 only changes its own install directory, so another earlier PATH entry can still
1038 launch an older copy.
1039
1040 Modern matched `codewhale`, `codew`, and compatibility copies update from the
1041 same verified bytes. Symlinks to the running binary are preserved. A different
1042 or unrelated sibling is named in the error and left untouched; no sibling is
1043 executed merely to guess its owner. Use the fresh-directory migration above
1044 for older installs with separate dispatcher/TUI binaries.
1045
1046 To retain a secondary package-managed install, use its manager:
1047
1048 ```bash
1049 npm install -g codewhale@latest
1050 # or
1051 cargo install codewhale-cli --locked --force
1052 ```
1053
1054 Homebrew uses `brew upgrade codewhale`; Omarchy uses `omarchy update`. These
1055 commands update their own copies, so verify PATH again afterward.
1056
1057 <a id="android--termux-arm64"></a>
1058
1059 ### Android / Termux arm64 (preview)
1060
1061 Termux runs on Android's Bionic libc and uses `$PREFIX` as its Unix prefix, so
1062 it needs a Termux-specific Android arm64 archive. The Linux arm64 release asset
1063 targets standard Linux with musl; Android uses a distinct Rust target, so the
1064 Linux asset should not be used there.
1065
1066 Install the minimum archive/runtime tools first:
1067
1068 ```bash
1069 pkg update
1070 pkg install -y ca-certificates curl tar gzip coreutils
1071 ```
1072
1073 When the release includes `codewhale-android-arm64.tar.gz`, install it with the
1074 archive's bundled installer. Passing `PREFIX="$PREFIX"` matters: the installer
1075 defaults to `~/.local`, while Termux users normally expect commands under
1076 `$PREFIX/bin`.
1077
1078 ```bash
1079 cd "$HOME"
1080 curl -L -O https://github.com/codewhale-hq/CodeWhale/releases/latest/download/codewhale-android-arm64.tar.gz
1081 curl -L -O https://github.com/codewhale-hq/CodeWhale/releases/latest/download/codewhale-bundles-sha256.txt
1082 sha256sum -c codewhale-bundles-sha256.txt --ignore-missing
1083
1084 tar xzf codewhale-android-arm64.tar.gz
1085 cd codewhale-android-arm64
1086 PREFIX="$PREFIX" ./install.sh
1087 hash -r
1088 ```
1089
1090 If you are validating from source or building a release candidate locally,
1091 install the build packages before running Cargo:
1092
1093 ```bash
1094 pkg install -y rust clang pkg-config make git
1095 cargo install codewhale-cli --locked # installs `codewhale`
1096 ```
1097
1098 The normal first-run setup path is implemented, but its Android interaction is
1099 still part of the preview QA above. Prefer provider environment variables for
1100 temporary credentials. `codewhale auth set` is available, but the Termux build
1101 has no supported OS keyring integration and falls back to file-backed secrets
1102 by writing `~/.codewhale/config.toml` and mirroring keys to
1103 `~/.codewhale/secrets/secrets.json`. Both are plaintext files protected by
1104 `0600` permissions and are not encrypted at rest.
1105
1106 ```bash
1107 codewhale auth set --provider deepseek
1108 codewhale auth status
1109 codewhale doctor
1110 ```
1111
1112 Maintainers should use this repeatable smoke checklist for a Termux / Android
1113 arm64 release candidate:
1114
1115 ```bash
1116 command -v codewhale codew
1117 test -x "$PREFIX/bin/codewhale"
1118 test -x "$PREFIX/bin/codew"
1119
1120 codewhale --version
1121 codewhale doctor
1122 codewhale exec --auto "run pwd"
1123 ```
1124
1125 Known limitations:
1126
1127 - Commands inherit Android's per-app UID, SELinux, and seccomp protections and
1128 any permissions granted to Termux. Codewhale's opt-in bubblewrap
1129 child-process sandbox is Linux-only and is not built on Android, so approved
1130 commands receive no Codewhale-specific filesystem narrowing.
1131 - The Termux build has no supported Android Keystore or desktop Secret Service
1132 integration. Use `codewhale auth status` to confirm the active source and
1133 prefer provider environment variables when file-backed plaintext storage is
1134 not acceptable.
1135 - Terminal rendering varies by Android terminal app. The TUI always owns the
1136 alternate screen. If a terminal app cannot render the full-screen TUI,
1137 use `codewhale exec` for headless runs instead.
1138
1139 ### China / mirror-friendly install
1140
1141 When installing from mainland China, configure mirrors for both **rustup**
1142 (the Rust toolchain installer) and **Cargo** (the package registry) to avoid
1143 TLS timeouts and download failures.
1144
1145 **Step 1: Install Rust via a rustup mirror**
1146
1147 ```bash
1148 # PowerShell
1149 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
1150 (New-Object Net.WebClient).DownloadFile('https://win.rustup.rs/x86_64', 'rustup-init.exe')
1151
1152 # git-bash / msys2
1153 export RUSTUP_DIST_SERVER=https://mirrors.tuna.tsinghua.edu.cn/rustup
1154 export RUSTUP_UPDATE_ROOT=https://mirrors.tuna.tsinghua.edu.cn/rustup/rustup
1155 ./rustup-init.exe -y --default-toolchain stable
1156
1157 # Linux / macOS
1158 export RUSTUP_DIST_SERVER=https://mirrors.tuna.tsinghua.edu.cn/rustup
1159 export RUSTUP_UPDATE_ROOT=https://mirrors.tuna.tsinghua.edu.cn/rustup/rustup
1160 curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
1161 ```
1162
1163 If the TUNA mirror is slow from your network, `rsproxy.cn` is another
1164 rustup mirror option for Linux/macOS:
1165
1166 ```bash
1167 export RUSTUP_DIST_SERVER=https://rsproxy.cn
1168 export RUSTUP_UPDATE_ROOT=https://rsproxy.cn/rustup
1169 curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
1170 ```
1171
1172 The `RUSTUP_DIST_SERVER` and `RUSTUP_UPDATE_ROOT` environment variables must
1173 be set **before** running rustup-init; the toolchain download otherwise hits
1174 the same TLS handshake problem as the installer.
1175
1176 **Step 2: Configure Cargo registry mirror**
1177
1178 ```toml
1179 # ~/.cargo/config.toml
1180 [source.crates-io]
1181 replace-with = "tuna"
1182
1183 [source.tuna]
1184 registry = "sparse+https://mirrors.tuna.tsinghua.edu.cn/crates.io-index/"
1185 ```
1186
1187 `rsproxy`, Tencent COS, and Aliyun OSS mirrors work the same way; pick whichever
1188 is fastest from your network.
1189
1190 ### Omarchy / AUR
1191
1192 On Omarchy, install the prebuilt AUR package:
1193
1194 ```bash
1195 omarchy pkg aur add codewhale-bin
1196 codewhale --version
1197 ```
1198
1199 `codewhale-bin` packages the same checksum-pinned Linux release archives as the
1200 other binary install paths and provides both `codewhale` and `codew`. It does
1201 not carry a separate Codewhale version; the existing `codewhale-tui`
1202 compatibility command remains an alias to the same runtime. Package updates
1203 arrive through `omarchy update`; the in-app updater leaves the pacman-owned
1204 binary to Omarchy.
1205
1206 The AUR update follows the matching Codewhale tag and release assets, so it may
1207 appear after the GitHub release while its generated `PKGBUILD` and `.SRCINFO`
1208 are validated. Release-maintainer instructions live in
1209 [`packaging/aur/README.md`](../packaging/aur/README.md).
1210
1211 ---
1212
1213 ### Windows
1214
1215 #### Windows Scoop
1216
1217 The `codewhale` package is listed in Scoop's main bucket:
1218
1219 ```powershell
1220 scoop update
1221 scoop install codewhale
1222 codewhale --version
1223 ```
1224
1225 Scoop manifests are maintained outside this repository's release workflow and
1226 can lag GitHub/npm/Cargo releases. Use npm or manual GitHub release downloads
1227 when you need the newest version immediately.
1228
1229 #### Windows winget
1230
1231 The published winget package is **`HunterBown.CodeWhale`** (verified in
1232 [microsoft/winget-pkgs](https://github.com/microsoft/winget-pkgs/tree/master/manifests/h/HunterBown/CodeWhale)
1233 on 2026-10-04; latest published version 0.10.0). It is a portable x64 package:
1234 winget downloads `codewhale-tui-windows-x64.exe`, installs it as the `codewhale`
1235 command, and pulls in the Microsoft Visual C++ 2015+ x64 runtime.
1236
1237 ```powershell
1238 winget install HunterBown.CodeWhale
1239 codewhale --version
1240 ```
1241
1242 Update with `winget upgrade HunterBown.CodeWhale` or `codewhale update`. Each
1243 version goes through winget-pkgs review after the GitHub Release, so winget can
1244 lag GitHub/npm/Cargo; use npm or the GitHub Release asset when you need the
1245 newest version immediately.
1246
1247 Known limits of the winget route:
1248
1249 * **x64 only.** The published manifest has no ARM64 installer. On Windows ARM64,
1250 use `npm install -g codewhale` under native ARM64 Node.js, or download
1251 `codewhale-windows-arm64.zip` from GitHub Releases.
1252 * **`codewhale` only.** The short `codew` alias is not installed by winget; use
1253 `codewhale`.
1254 * The manifest in this repository (`packaging/winget/`) is not the one winget
1255 serves; see [`packaging/winget/README.md`](../packaging/winget/README.md).
1256
1257 #### Windows NSIS Installer
1258
1259 A standalone NSIS-based installer is available starting with v0.8.50 for
1260 Windows users who prefer a traditional double-click setup (no npm, no Scoop, no
1261 Cargo required).
1262
1263 The NSIS installer currently contains the Windows x64 binaries. Windows ARM64
1264 users should install through npm running under native ARM64 Node.js or download
1265 `codewhale-windows-arm64.zip` from the same release; both paths then use native
1266 ARM64 binaries.
1267
1268 **Download** `CodeWhaleSetup.exe` from the
1269 [Releases page](https://github.com/codewhale-hq/CodeWhale/releases/latest).
1270
1271 **Install** by double-clicking the setup executable. The installer:
1272
1273 - Installs `codewhale.exe` and `codew.exe` side-by-side (single binary, no `codewhale-tui.exe`) into
1274 `%LOCALAPPDATA%\Programs\CodeWhale\bin`
1275 - Installs `codewhale.bat`, which prefers Windows Terminal (`wt.exe`) when it is on `PATH` and
1276 otherwise launches the exe directly
1277 - Creates a current-user Start Menu shortcut that opens that launcher, not the raw `.exe`
1278 - Adds the install directory to the **current user** `PATH`
1279 - Registers in Windows **Apps & Features** for easy uninstall
1280
1281 Uninstall removes the binaries, `codewhale.bat`, the Start Menu shortcut, and the user `PATH` entry.
1282
1283 **Silent install** (for IT admins, SCCM, Intune):
1284
1285 ```powershell
1286 CodeWhaleSetup.exe /S
1287 ```
1288
1289 The installer is per-user and does not request elevation. Run silent installs in
1290 the target user's context, or use a deployment tool that can run the installer
1291 for each user profile that needs Codewhale.
1292
1293 The release-built installer is currently unsigned and may trigger Windows
1294 SmartScreen. Verify the SHA-256 checksum from `codewhale-artifacts-sha256.txt`
1295 before deploying, and sign the installer in your internal deployment pipeline if
1296 your environment requires signed application packages.
1297
1298 **Build the installer yourself** (requires [NSIS](https://nsis.sourceforge.io)):
1299
1300 ```powershell
1301 cd scripts\installer
1302 # Place codewhale.exe and codew.exe here (single binary, no codewhale-tui.exe), then:
1303 makensis /DVERSION=<version> codewhale.nsi
1304 ```
1305
1306 **Manual fallback** — if the installer is blocked by group policy, see the
1307 [CLASSROOM_INSTALL.md](CLASSROOM_INSTALL.md) guide for step-by-step PowerShell
1308 commands.
1309
1310 > **Deploying to a classroom or lab?** See the full
1311 > [Classroom Install Checklist](CLASSROOM_INSTALL.md) for silent install,
1312 > API key provisioning, imaging notes, and troubleshooting.
1313
1314 <a id="freebsd"></a>
1315
1316 ### FreeBSD, cross-compiling, Windows source builds
1317
1318 #### FreeBSD 14+ source-build workaround (#1097)
1319
1320 FreeBSD has no prebuilt GitHub Release asset — `npm install -g codewhale` intentionally
1321 fails with `Unsupported platform: freebsd` and points to Cargo. Install from source:
1322
1323 ```bash
1324 pkg install -y rust pkgconf git
1325 cargo install codewhale-cli --locked # installs `codewhale`
1326 codewhale --version
1327 codewhale doctor
1328 ```
1329
1330 The `rquickjs` FreeBSD bindings are generated at build time via `bindgen` (see
1331 `1582ba965`/`5eb0385e8`). No separate `pkg install codewhale` port exists yet —
1332 a native port is tracked as the follow-up to #1097 under `packaging/freebsd/`
1333 (contributions welcome). Validate with `cargo check --target x86_64-unknown-freebsd -p codewhale-cli --locked`
1334 on the release branch; the 7×1 release matrix (Linux musl x64/arm64,
1335 Android arm64, macOS x64/arm64, Windows x64/arm64) stays 7 targets — FreeBSD is a
1336 source-build target, not a prebuilt asset.
1337
1338 #### Cross-compiling from x64 to ARM64 Linux
1339
1340 The release asset uses `aarch64-unknown-linux-musl` and is built on a native ARM
1341 runner. If you want to build a GNU-linked ARM64 Linux binary on an x64 Linux
1342 host (e.g. for a HarmonyOS / openEuler ARM64 thin-and-light), use
1343 [`cross`](https://github.com/cross-rs/cross), which wraps the official Rust
1344 cross-targets in a Docker container:
1345
1346 ```bash
1347 # Once
1348 rustup target add aarch64-unknown-linux-gnu
1349 cargo install cross --locked
1350
1351 # Per build
1352 cross build --release --target aarch64-unknown-linux-gnu -p codewhale-cli # single binary
1353 ```
1354
1355 The resulting binary lands in
1356 `target/aarch64-unknown-linux-gnu/release/codewhale`. Copy it to the ARM64 host
1357 (e.g. via `scp`) and make it executable. This local GNU build is distinct from
1358 the portable musl release asset; either executable can be copied under the
1359 `codew` convenience name.
1360
1361 If you don't have Docker available, install the cross-linker directly and let
1362 Cargo do the work:
1363
1364 ```bash
1365 sudo apt-get install -y gcc-aarch64-linux-gnu
1366 rustup target add aarch64-unknown-linux-gnu
1367
1368 cat >> ~/.cargo/config.toml <<'EOF'
1369 [target.aarch64-unknown-linux-gnu]
1370 linker = "aarch64-linux-gnu-gcc"
1371 EOF
1372
1373 cargo build --release --target aarch64-unknown-linux-gnu -p codewhale-cli # single binary
1374 ```
1375
1376 Producing `aarch64-unknown-linux-musl` while cross-compiling requires an
1377 appropriate musl cross-linker. The release workflow avoids that extra moving
1378 part by building and launching the musl binary on GitHub's native ARM runner.
1379
1380 #### Windows build from source
1381
1382 Building on Windows requires the **MSVC C toolchain** from
1383 [Visual Studio Build Tools](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022)
1384 (the free workload-selectable installer, not the full IDE).
1385
1386 **Prerequisites (Windows)**
1387
1388 1. Install Visual Studio 2022 Build Tools — select the **"Desktop development
1389 with C++"** workload.
1390 2. Install [Rust](https://rustup.rs) 1.89+ (see the
1391 [China mirror instructions](#china--mirror-friendly-install) above if
1392 downloading from mainland China).
1393 3. Install [Git for Windows](https://git-scm.com/download/win) (provides `git`
1394 and the `git-bash` terminal).
1395
1396 **Recommended terminals**: Windows Terminal, `git-bash`, or PowerShell.
1397 `cmd.exe` works but has a small buffer and limited PATH behavior.
1398
1399 **Setting up the MSVC environment**
1400
1401 Visual Studio Build Tools install `cl.exe` to a versioned directory but do
1402 **not** add it to `PATH` globally. You must set the environment manually or
1403 use a Developer Command Prompt. The required variables are:
1404
1405 ```powershell
1406 # Adjust version numbers to match your installation
1407 $msvc = "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\14.44.35207"
1408 $sdk = "C:\Program Files (x86)\Windows Kits\10"
1409 $sdkv = "10.0.26100.0"
1410
1411 $env:INCLUDE = "$msvc\include;$msvc\atlmfc\include;$sdk\Include\$sdkv\ucrt;$sdk\Include\$sdkv\um;$sdk\Include\$sdkv\shared"
1412 $env:LIB = "$msvc\lib\x64;$msvc\atlmfc\lib\x64;$sdk\Lib\$sdkv\ucrt\x64;$sdk\Lib\$sdkv\um\x64"
1413 $env:LIBPATH = "$msvc\lib\x64;$msvc\atlmfc\lib\x64"
1414 $env:CC = "$msvc\bin\Hostx64\x64\cl.exe"
1415 $env:CXX = "$msvc\bin\Hostx64\x64\cl.exe"
1416 $env:PATH = "$msvc\bin\Hostx64\x64;$env:PATH"
1417 ```
1418
1419 Alternatively, open a **"Developer Command Prompt for VS 2022"** (available
1420 from the Start Menu after installing Build Tools), which runs `vcvars64.bat`
1421 to configure all of the above automatically. Then add `cargo` to `PATH` inside
1422 that session and run `cargo build` from the project root.
1423
1424 **Cargo registry mirror** — on Windows the mirror config goes to
1425 `%USERPROFILE%\.cargo\config.toml`. See [Step 2 above](#china--mirror-friendly-install).
1426
1427 **Build**
1428
1429 ```bash
1430 git clone https://github.com/codewhale-hq/CodeWhale.git
1431 cd CodeWhale
1432 set CARGO_HTTP_CHECK_REVOKE=false # may be needed behind some Chinese ISPs
1433 cargo build --release
1434 ```
1435
1436 The Cargo-built binary appears at `target\release\codewhale.exe`. Release
1437 packaging separately exposes the same executable as `codew.exe`.
1438
1439 > Prefer not to build? Install via npm, Cargo, GitHub Releases, or the CNB
1440 > mirror — see the sections above.
1441
1442 ### Older-release and regional troubleshooting
1443
1444 #### `Unsupported architecture: arm64 on platform linux`
1445
1446 You're on a release earlier than v0.8.8 that doesn't publish Linux ARM64
1447 binaries. Use the GitHub installer in a fresh directory as described above, or use
1448 `cargo install` per [Section 4](#5-cargo-and-building-from-source).
1449
1450 #### `MISSING_COMPANION_BINARY` after upgrading an older install
1451
1452 The current single binary runs the TUI in-process and does not require a
1453 companion executable. This error identifies a stale pre-v0.9.5 dispatcher.
1454 Use the fresh-directory GitHub migration above, then verify the selected
1455 `codewhale` and `codew` paths. Do not download another separate runtime.
1456
1457 #### `codewhale update` reports `no asset found for platform codewhale-linux-aarch64`
1458
1459 Older updaters used Rust architecture names that did not match the published
1460 asset names. Use the official installer in a fresh directory as described above,
1461 then run the newly installed command by its full path.
1462
1463 #### npm download is slow or times out from mainland China
1464
1465 On Linux x64 the npm wrapper already probes GitHub Releases and the CNB
1466 first-party checksum manifests in parallel and downloads binaries only from
1467 the first source that validates. You do not need `CODEWHALE_USE_CNB_MIRROR=1`
1468 for that automatic path.
1469
1470 If both first-party sources fail, set `CODEWHALE_RELEASE_BASE_URL` to a
1471 mirrored release-asset directory (rsproxy, TUNA, Tencent COS, Aliyun OSS),
1472 or skip npm entirely and use the Cargo mirror setup in
1473 [Section 4](#5-cargo-and-building-from-source). The legacy
1474 `DEEPSEEK_TUI_RELEASE_BASE_URL` name is still accepted. `CODEWHALE_USE_CNB_MIRROR=1`
1475 still forces CNB only on Linux x64 / OpenHarmony x64.
1476
1477 #### `codewhale update` is blocked by GitHub from mainland China
1478
1479 `codewhale update` prefers GitHub Releases. On supported Linux x64 targets,
1480 a failed GitHub manifest permits the matching CNB manifest and binary fallback.
1481 If GitHub metadata is also unreachable, explicitly select a known published CNB
1482 version (`CODEWHALE_USE_CNB_MIRROR=1 CODEWHALE_VERSION=X.Y.Z codewhale update`)
1483 or a binary mirror below. Existing newer builds are kept.
1484
1485 Building from the CNB source mirror with Cargo is a secondary option. Cargo
1486 installs its own `codewhale` command:
1487
1488 To check the latest release without downloading or replacing binaries, run
1489 `codewhale update --check`.
1490
1491 ```bash
1492 cargo install --git https://cnb.cool/codewhale.net/codewhale --tag vX.Y.Z codewhale-cli --locked --force # single binary
1493 ```
1494
1495 If you operate a binary asset mirror, `codewhale update` can use it directly:
1496
1497 ```bash
1498 CODEWHALE_RELEASE_BASE_URL=https://your-mirror.example.com/CodeWhale/vX.Y.Z/ \
1499 CODEWHALE_VERSION=X.Y.Z \
1500 codewhale update
1501 ```
1502
1503 The mirror directory must contain `codewhale-artifacts-sha256.txt` and the
1504 platform binaries from the GitHub release. The legacy
1505 `DEEPSEEK_TUI_RELEASE_BASE_URL` mirror variable remains supported as an alias.
1506
1507 `codewhale update` only talks HTTPS, and only to GitHub's release hosts, the CNB
1508 mirror, and the host of the `CODEWHALE_RELEASE_BASE_URL` you set; every
1509 redirect hop is held to the same rule, so a plain-`http://` mirror is refused.
1510 A private mirror therefore works as soon as its base URL is HTTPS. If that
1511 mirror redirects asset downloads to a separate download host (a CDN or an
1512 object-store domain), name that host too:
1513
1514 ```bash
1515 CODEWHALE_UPDATE_ALLOWED_HOSTS=cdn.your-mirror.example.com,objects.example.net \
1516 CODEWHALE_RELEASE_BASE_URL=https://your-mirror.example.com/CodeWhale/vX.Y.Z/ \
1517 CODEWHALE_VERSION=X.Y.Z \
1518 codewhale update
1519 ```
1520
1521 The error message for a refused host names it and this variable.
1522
1523 ### Windows and npm-download troubleshooting
1524
1525 #### Windows: `TLS handshake eof` or `CRYPT_E_REVOCATION_OFFLINE` from `rustup-init`
1526
1527 The TLS handshake to `static.rust-lang.org` fails from behind the GFW or
1528 certain Chinese ISPs. Set the rustup mirror environment variables **before**
1529 running the installer:
1530
1531 ```bash
1532 # git-bash / msys2
1533 export RUSTUP_DIST_SERVER=https://mirrors.tuna.tsinghua.edu.cn/rustup
1534 export RUSTUP_UPDATE_ROOT=https://mirrors.tuna.tsinghua.edu.cn/rustup/rustup
1535 ./rustup-init.exe -y --default-toolchain stable
1536 ```
1537
1538 If you see `CRYPT_E_REVOCATION_OFFLINE` from Cargo after Rust is installed,
1539 also set `CARGO_HTTP_CHECK_REVOKE=false` during `cargo build`.
1540
1541 #### Windows: MSVC compiler (`cl.exe`) not found during `cargo build`
1542
1543 Visual Studio Build Tools do not add `cl.exe` to the global `PATH`. Either:
1544
1545 1. Open **"Developer Command Prompt for VS 2022"** from the Start Menu, add
1546 `%USERPROFILE%\.cargo\bin` to `PATH` in that window, and run `cargo build`
1547 from there; or
1548 2. Set the MSVC environment variables manually — see the
1549 [Windows build from source](#windows-build-from-source) section for the
1550 PowerShell snippet.
1551
1552 Verify the compiler is reachable: `cl.exe /?` should print help text.
1553
1554 #### Windows: `拒绝访问 (os error 5)` when Cargo executes build scripts
1555
1556 Third-party antivirus software (Huorong, 360, Kaspersky, etc.) may block
1557 Cargo from executing freshly-compiled build-script binaries
1558 (e.g. `libsqlite3-sys`, `aws-lc-sys`, `instability`). The error is
1559 path-agnostic — moving `target-dir` does not help.
1560
1561 **Symptoms**: `could not execute process ... build-script-build (never executed)`
1562
1563 **Workarounds** (pick one):
1564
1565 1. **Add the project's `target/` directory to your AV exclusions list.**
1566 2. **Close the antivirus software temporarily** during `cargo build`.
1567 3. **Use the GitHub Release installer/archive instead** — the release assets
1568 ship prebuilt binaries and skip the Cargo build entirely
1569 ([Section 6](#3-manual-download-from-github-releases)).
1570 4. **Use `cargo install codewhale-cli --locked`** from crates.io — this
1571 changes the binary path, which some AV tools treat differently.
1572
1573 To verify that the build-script binary itself is valid (not corrupted), locate
1574 it under `target/debug/build/<crate>/build-script-build` and run it manually:
1575
1576 ```bash
1577 target/debug/build/libsqlite3-sys-*/build-script-build
1578 # If this runs but panics with "NotPresent" (no C compiler), the binary is
1579 # fine — the AV is blocking Cargo's process-spawning path specifically.
1580 ```
1581
1582 #### npm binary download times out
1583
1584 If `codewhale` waits several seconds and prints `connect ETIMEDOUT` or
1585 `EAI_AGAIN` while fetching from `github.com`, the npm wrapper installed
1586 successfully but the prebuilt binary download is blocked or unreliable on
1587 your network. This download is separate from the npm registry package
1588 download. On Linux x64 the wrapper first races the small GitHub and CNB
1589 checksum manifests and does not wait for a full GitHub binary to time out
1590 before using a valid CNB manifest.
1591
1592 Use one of these paths:
1593
1594 1. Set a proxy and retry:
1595
1596 ```bash
1597 export HTTPS_PROXY=http://your-proxy:port
1598 codewhale
1599 ```
1600
1601 2. Mirror the release assets internally and set `CODEWHALE_RELEASE_BASE_URL`:
1602
1603 ```bash
1604 export CODEWHALE_RELEASE_BASE_URL=https://your-mirror.example.com/CodeWhale/
1605 codewhale
1606 ```
1607
1608 The directory must contain `codewhale-artifacts-sha256.txt` and the platform
1609 binaries from the GitHub release.
1610
1611 3. Install via Cargo, which builds locally and does not download GitHub release
1612 assets. See [Section 4](#5-cargo-and-building-from-source).
1613
1614 4. Download both matching `codewhale` and `codew`
1615 binaries from the [Releases page](https://github.com/codewhale-hq/CodeWhale/releases),
1616 place them in a directory on `PATH`, and make them executable. See
1617 [Section 6](#3-manual-download-from-github-releases).
1618
1618 lines MARKDOWN