Clash Nyanpasu Auto-Update Mechanism and Core Version Management: A Technical Deep Dive
Clash Nyanpasu implements a self-contained update pipeline that generates cryptographically signed update.json metadata files from GitHub releases, while centrally managing multiple proxy core versions through manifest/version.json to enable seamless automatic updates and runtime core switching between Mihomo, Clash-RS, and Clash Premium.
The libnyanpasu/clash-nyanpasu repository maintains a sophisticated auto-update mechanism that eliminates manual binary management for users across platforms. This system automatically resolves the latest releases from various upstream Clash cores, generates platform-specific metadata, and publishes version-controlled update manifests. Understanding this architecture reveals how the application handles secure, cross-platform distribution while supporting multiple proxy engine variants simultaneously.
How the Auto-Update Pipeline Works
The update process centers on scripts/updater.ts, which orchestrates the creation of machine-readable manifests that the UI consumes to download correct binaries for the user's operating system and CPU architecture.
Resolving Releases and Building update.json
The resolveUpdater() function queries the repository's tags to identify the most recent stable release starting with v. It then resolves all associated binary assets and their corresponding .sig signature files. The script constructs a JSON object containing name, notes, pub_date, and a platforms map that associates specific OS/architecture combinations with signed download URLs.
Proxy Acceleration and Asset Publication
To mitigate GitHub throttling in certain regions, the script generates a proxy-accelerated variant of the update manifest. The getGithubUrl() helper in scripts/utils/utils.ts rewrites all asset URLs to route through https://hub.fastgit.xyz/, creating an update-proxy.json alongside the standard update.json. Both files are published to a dedicated GitHub release tagged updater. If this release doesn't exist, the script creates it as a pre-release, deletes stale update*.json assets, and uploads fresh copies (lines 124-165 in updater.ts).
Cryptographic Verification and Local Caching
Each binary asset includes a detached signature file accessed via getSignature(). The updater embeds these signatures into the JSON metadata, enabling the client to verify integrity before execution. For offline environments or development workflows, invoking the CLI with --cache-path triggers saveToCache() to store the generated JSON files locally, bypassing network checks on subsequent runs.
Core Version Management Architecture
Clash Nyanpasu supports multiple proxy engines (mihomo, clash-rs, clash-premium, clash-meta) simultaneously. The versioning logic spans three architectural layers to maintain consistency across platforms.
Central Version Registry
The file manifest/version.json serves as the single source of truth for all supported cores. It stores semantic versions (or git hashes) under the latest key for each engine, alongside an arch_template mapping that defines per-platform binary naming conventions:
{
"latest": {
"mihomo": "v1.19.20",
"clash_rs": "v0.9.4",
"clash_premium": "2023-09-05-gdcc8d87",
"clash_rs_alpha": "0.9.4-alpha+sha.e11288b"
},
"arch_template": {
"clash_rs": {
"windows-x86_64": "clash-x86_64-pc-windows-msvc.exe",
"darwin-arm64": "clash-aarch64-apple-darwin"
}
}
}
Source: manifest/version.json
Per-Core Manifest Abstractions
Located in scripts/manifest/, TypeScript files like clash-rs.ts, clash-premium.ts, and clash-meta.ts expose three critical properties for the downloader: URL_PREFIX (the base GitHub releases URL), VERSION (pulled from version.json), and ARCH_MAPPING (the platform-specific filename templates). For example, the Clash-RS manifest exports:
export const CLASH_RS_MANIFEST: ClashManifest = {
URL_PREFIX: 'https://github.com/Watfaq/clash-rs/releases/download/',
VERSION: versionManifest.latest.clash_rs,
ARCH_MAPPING: versionManifest.arch_template.clash_rs,
};
Source: scripts/manifest/clash-rs.ts
Runtime URL Resolution
The scripts/utils/resource.ts module handles dynamic core switching at runtime. Given a core name and the current platform identifier (e.g., win32-x64 or darwin-arm64), it selects the appropriate manifest and constructs the final download URL using the pattern ${URL_PREFIX}${VERSION}/${ARCH_MAPPING[platform]}. This enables the UI to fetch the correct binary immediately when users switch between Mihomo, Clash-RS, or Clash Premium engines.
Nightly Build Variant
For bleeding-edge releases, scripts/updater-nightly.ts mirrors the stable pipeline but targets the pre-release tag instead of updater. It injects the short Git hash into the version string (e.g., v1.2.3-alpha+abcd123), allowing users to track specific commit builds while maintaining the same cryptographic verification and platform detection logic implemented in the stable updater.
Typical Update Flow Implementation
When the application checks for updates, it executes the following sequence:
// 1. Load the updater JSON from GitHub or FastGit proxy
const updaterUrl = `${githubRepoUrl}/releases/download/updater/update.json`;
const updaterInfo = await fetch(updaterUrl).then(r => r.json());
// 2. Detect current platform (win64, darwin-aarch64, etc.)
const platform = detectPlatform();
// 3. Extract download URL and signature for current arch
const { url, signature } = updaterInfo.platforms[platform];
// 4. Verify cryptographic signature
await verifySignature(url, signature);
// 5. Download and install the binary
await downloadFile(url, targetPath);
For manual core switches initiated through the UI settings, the application bypasses the updater JSON entirely and calls the resource resolver directly, computing the URL from manifest/version.json and the per-core manifests in real-time.
Summary
- Auto-update generation: The
scripts/updater.tsscript synthesizesupdate.jsonandupdate-proxy.jsonfiles containing signed binary URLs for every supported platform/architecture combination. - Release tagging: Stable updates publish to the
updaterrelease tag, while nightly builds usepre-releasewith git-hash versioning. - Centralized versioning:
manifest/version.jsonmaintains authoritative version strings and architecture templates for all cores (mihomo, clash-rs, clash-premium). - Runtime resolution:
scripts/utils/resource.tsconstructs download URLs dynamically using per-core manifests, enabling instant switching between proxy engines. - Security: Detached Ed25519 signature files (
.sig) are embedded in update metadata and verified before execution viagetSignature().
Frequently Asked Questions
How does Clash Nyanpasu verify the integrity of auto-updates?
The updater embeds cryptographic signatures into the update.json metadata via the getSignature() function. Before executing any downloaded binary, the client verifies the signature against the corresponding .sig file fetched from the GitHub release assets, ensuring the binary hasn't been tampered with during transit or storage.
What is the difference between stable and nightly auto-updates?
Stable releases use scripts/updater.ts and publish to the updater tag with semantic versioning (e.g., v1.2.3), while nightly builds use scripts/updater-nightly.ts targeting the pre-release tag. Nightly versions append the short Git hash (e.g., v1.2.3-alpha+abcd123) to identify specific commit builds and provide granular debugging information.
How does Clash Nyanpasu handle slow GitHub downloads in certain regions?
The pipeline generates a proxy-accelerated manifest (update-proxy.json) where all URLs are rewritten through https://hub.fastgit.xyz/ via the getGithubUrl() utility. The UI automatically selects this mirror when detecting network conditions that benefit from the FastGit CDN, significantly improving download speeds in regions with GitHub throttling or connectivity issues.
Can users switch proxy cores without waiting for an auto-update?
Yes. When users select a different core in the UI (e.g., switching from Mihomo to Clash-RS), the application bypasses the updater JSON and invokes scripts/utils/resource.ts to resolve the download URL directly from manifest/version.json and the per-core manifest files. This enables immediate downloading of the selected core version without requiring a new updater release.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →