The three .github/workflows files (release.yml, compat-daily.yml,
cache-cleanup-weekly.yml) all target the GitHub API:
- release.yml uses `gh release create`
- compat-daily.yml does `git push https://x-access-token@github.com/...`
to a `badges` branch
- cache-cleanup-weekly.yml uses `gh cache delete`
On Gitea Actions these silently mis-route to GitHub with a Gitea-issued
GITHUB_TOKEN, which github.com rejects ("Invalid username or token") —
so every scheduled run fails.
Drop them on secure-main (upstream main keeps them for the original
GitHub repo, untouched) and add .gitea/workflows/release.yml that:
- triggers on tag push v* or manual workflow_dispatch
- builds release notes from the changelog window since the prior tag
- creates the release via Gitea API, or refreshes assets if it already
exists (so re-runs are idempotent)
- attaches install.sh + install.ps1 so the README's
/releases/latest/download/install.{sh,ps1} URLs resolve
Tag a release with:
git tag v1.0.0 && git push origin v1.0.0
compat-daily.yml writes a fresh ~/.npm cache entry per run (key
embeds github.run_id) and reads previous entries via restore-keys.
GitHub's 7-day inactivity expiry never fires — the daily restore-
keys match counts as access — so entries accumulate until the 10 GB
per-repo cap kicks in and LRU starts evicting useful caches.
Weekly purge: list every cache, delete it. Next compat-daily run
repopulates ~/.npm fresh from npm-registry (one extra ~80 MB
download per week, trivial cost). Sunday 04:00 UTC cron, with a
workflow_dispatch escape hatch for manual cleanup. `actions: write`
permission scoped to this workflow only.
The Update section in README{,_ZH,_JP}.md still claimed cli.cjs's
drift detection would auto-re-patch on next launch — that block was
removed in v1.1.1. Rewrite the section to describe the actual flow:
running `claude update` triggers the patched redirect into
install.{sh,ps1}, which pulls @anthropic-ai/claude-code-<plat>@latest
from npm. The end result for the user is the same as a vanilla
upgrade — current Claude, with patches applied — in one command.
install.{sh,ps1}'s post-install footer mirrors that explanation so
users learn about the redirect at install time, not after they get
confused by `claude update` doing more than they expected.
For users who'd rather not take that on faith, expose the
latest-verified Claude version directly: compat-daily.yml now
force-pushes a {schemaVersion, label, message, color} JSON to a
dedicated `badges` branch after every successful run, and a
shields.io endpoint badge in all three READMEs reads it. The branch
holds nothing else and is never read as source — same posture as
published-by-CI badges in other public repos. Skipped on PRs (fork
PRs lack the token).
Three classes of bugs collapse into one fix:
1. `claude update` was actively destructive — its "unknown install
type" fallback overwrote ~/.bun/bin/bun on macOS (downgrading the
user's Bun and crashing cli.original.cjs with "Expected CommonJS
module to have a function wrapper") and wrote the new binary
outside our scan path on Windows ("Successfully updated" without
actually updating anything visible to clawgod). Patched to redirect
into clawgod's own install.{sh,ps1} as the single self-update path.
PowerShell 5.1 specifics handled inline: use `irm` not `iwr` (its
-useb mode returns byte[] for .Content, choking `iex`); read
HTTPS_PROXY/HTTP_PROXY from env explicitly and pass via `-Proxy`
(PS 5.1's iwr only reads IE settings, ignoring env); ship the
PowerShell payload via `-EncodedCommand` to bypass arg quoting.
2. Stale install sources removed:
- `~/.local/share/claude/versions/` and `Programs\claude-code` only
ever grow on a healthy clawgod install (`claude update` is now
patched out). Picking from them = pinning to whatever was
downloaded on first run, forever.
- `claude.orig` / `claude.orig.exe` backups are a frozen snapshot.
They exist for `--uninstall` to restore vanilla Claude, never as
a fresh install source.
Detection now always routes to npm-global → bun-global → npm-
registry, all of which carry actually-current versions.
3. cli.cjs's drift detection scanned the same stale `versions/` and
could only retract a fresher version install.{sh,ps1} just pulled
from npm registry, putting users into an infinite re-patch loop.
Removed entirely. The patched `claude update` → install.{sh,ps1}
redirect is now the single version-upgrade entry point.
install.{sh,ps1} now sanity-checks bun's ability to load
cli.original.cjs before writing the launcher and fails fast when the
user's Bun lags Anthropic's embedded canary (currently 1.3.14, while
bun.sh's stable still ships 1.3.13). The error message spells out
exactly which `bun upgrade --canary` path to take, including the
scoop case where the bun shim refuses self-replace.
release.yml gets `FORCE_JAVASCRIPT_ACTIONS_TO_NODE24` for parity with
compat-daily.yml — never run JS-based actions on Node 20 across our
workflows.
Fixes#51
Daily CI exposed a second set -e trap: under bash 5, `X=$(which foo)`
where `foo` isn't installed lets `which`'s exit code 1 carry through
the assignment and trips errexit. Switch both lookups (install path
and uninstall path) to `$(command -v claude 2>/dev/null || true)` —
POSIX builtin, robust on minimal images that no longer ship `which`,
and explicit about the miss being non-fatal.
While here, harden compat-daily.yml:
- Force JS-based actions onto Node 24 (FORCE_JAVASCRIPT_ACTIONS_TO_NODE24)
and align scripts via actions/setup-node@v4 — silences the deprecation
warning and keeps patch.mjs / extract-natives.mjs on the same runtime.
- Replace the curl-install + bun-upgrade dance with oven-sh/setup-bun@v2
(canary), which already caches the binary by commit hash.
- Cache ~/.npm so the ~80 MB claude-code-<plat> tarball is only re-fetched
on actual upstream bumps, not every run.
Under `set -e`, both fallback scan calls (npm-global, bun-global) sat
in positions where `scan_node_modules_root` returning 1 on a clean
miss was the final command of a `&&` list / then-block, so the script
exited before ever reaching the npm-registry fallback. The daily CI
run on a clean Linux runner caught this — locally it stayed hidden
because there was always a bun-global hit on the second scan.
Both calls now `|| true` and fall through to the npm-registry path.
Also drop the multi-OS matrix from compat-daily.yml. A Linux failure
is a near-certain proxy for cross-platform breakage upstream, and
macOS / Windows runner minutes cost 10x / 2x — not the right shape
for a daily scout.
Smoke-test install.sh end-to-end on Ubuntu (x64+arm) and macOS
(Intel+Apple Silicon) every morning. Asserts patch.mjs reports
"0 failed" and that `claude --version` boots without the Bun
CJS-wrapper panic surfaced by the v2.1.121 / Bun 1.3.14 upgrade.
Thanks @shadow1ng for the suggestion that a daily CI run is the
right shape to catch upstream Bun-version drift before users do.
Pushing a tag matching v* now creates / updates a GitHub release with
install.sh and install.ps1 attached, plus auto-generated changelog
(commit log between prev and current tag) and standard install
snippets in the body. Idempotent: re-pushing a tag updates the
existing release rather than failing.
For routine patch releases this replaces the manual `gh release create`
flow. For larger releases that need a hand-written narrative, you can
still overwrite the body via `gh release edit` afterward.