Preface¶
The DSH (DeepSeek Harness) desktop client controls the rollout ratio of nightly builds via the electron-updater staging mechanism: the stagingPercentage (0–100) in the official feed determines how many people receive the new version. Technically, whether a machine is included depends on the deterministic bucket value of the UUID in its local .updaterId file. This means some machines have bucket values naturally skewed to the back, and if the rollout ratio isn’t large enough, they will never receive updates.
dsh-staging-hunter solves this problem: it pins the .updaterId to a target bucket value (default 1%) and automatically corrects it if the file is changed back to a random value by the application. Maintained by ChenXu233, MIT license, client-side plugin.
What is this¶
In one sentence: A DSH desktop plugin used to pin the electron-updater staging identity, ensuring the local machine consistently lands in the first batch of nightly grayscale rollouts.
It does not modify the package source, nor does it skip signature verification. It only changes a local “who am I” tag.
How it works: Pinning the low-order bucket value of .updaterId¶
First, let’s look at the original logic by which the DSH desktop client determines if a machine is included (located in app.asar -> node_modules/electron-updater/out/AppUpdater.js):
stagingPercentage = parseInt(updateInfo.stagingPercentage, 10) / 100
const val = UUID.parse(stagingUserId).readUint32BE(12)
const percentage = val / 0xffffffff
return percentage < stagingPercentage // 严格小于
There are two key points:
- The bucket value is a deterministic hash of the UUID, taken from bytes 12–15 of the UUID. Once a machine has a
.updaterId, it will forever land in a fixed bucket position. - This is a strict less-than comparison. As long as the
stagingPercentageis greater than the machine’s bucket value, the machine is in the cohort.
Therefore, lowering the bucket value ensures stable inclusion in the cohort. The plugin’s behavior (as per README):
- At startup, read
.updaterId; if the bucket value is already below the ceiling, use the existing identity and do not change the UUID. - Otherwise, generate a valid v4 UUID, precisely write
bytes[12..15]to the target bucket value, back up the original file, and write it back. - Store the pinned UUID into
.staging-hunter.json(sidecar) to ensure identity stability across restarts. - Use
fs.watchcombined with periodic inspection to guard the file: immediately correct it if the application changes it back to a random value. - Automatically close the watcher and timers upon plugin uninstallation.
Installation and Enablement¶
Install from npm (recommended):
dsh plugin add dsh-staging-hunter
After approving the prompts, restart DSH, and the plugin will automatically pick a low-order bucket UUID and start guarding it.
You can also hook it up to your profile from source or manually. The repository will not automatically write to your profile. Two ways:
As a bundle package, first put the repository in the profile’s node_modules (use directory junctions for Windows to avoid triggering pnpm reinstall):
cmd //c mklink /J "%USERPROFILE%\.dsh\profiles\desktop\node_modules\dsh-staging-hunter" "E:\git\dsh-staging-hunter"
Then add a line "dsh-staging-hunter" to both the dependencies and dsh.profile.bundles in ~/.dsh/profiles/desktop/package.json.
Or directly write it into the profile’s patch layer by appending to ~/.dsh/profiles/desktop/cordis.patch.yml:
- insert:
- id: dsh-staging-hunter
name: 'dsh-staging-hunter'
config:
targetPercentage: 1
After modifying, restart the DSH desktop client. You should see the following in the startup logs:
[staging-hunter] pinned updaterId (startup) -> <uuid> bucket=1.000000%
[staging-hunter] watching ...\.updaterId ceiling=1% pinnedBucket=1.000000%
If these two log lines appear, it indicates the identity has been pinned and the guard has started.
Configuration¶
Optional configuration is as follows, using default values if not configured:
| Key | Default | Description |
|---|---|---|
enabled |
true |
Master switch |
targetPercentage |
1 |
Bucket value ceiling (%). Bucket values lower than this are considered to be in the first batch |
uuid |
'' |
The pinned UUID; leave empty to auto-select/generate |
updaterIdPath |
'' |
.updaterId path override; leave empty to auto-detect |
checkIntervalMs |
60000 |
Inspection interval; 0 means relying solely on fs.watch |
Typical Usage¶
Default is out-of-the-box: after deployment, restart the DSH desktop client, then confirm from the startup logs that the plugin has finished initialization. The first log line shows the result of pinning updaterId at startup, and the second confirms the guard target and ceiling are effective.
If the .updaterId path on the machine is not in the default detection range, use updaterIdPath to point to it; if you want to use a self-prepared UUID, fill in uuid, leaving it empty will cause the plugin to generate one automatically. If both parties only need to respond to file changes, you can set checkIntervalMs to 0 and leave it entirely to fs.watch.
Suitable Scenarios and Notes¶
Suitable for DSH desktop users who want to consistently follow the nightly builds, but whose machines have high bucket values and haven’t received new versions for a long time.
A few points to note:
- Integrity is not affected. The plugin only modifies the local identity tag; the package is still downloaded from the official address and verified for signature based on
sha512and the installer’spublisherNamein the feed. - A restart is required.
AppUpdateruses aLazycache forstagingUserIdPromise, so the written value only takes effect in the next update check upon startup. - Nightly builds themselves carry risk; you will consistently receive RC versions and may encounter crashes or breaking changes.
- Behavior change: The old behavior was “if not in the cohort, stay on the current version”; with the plugin installed, it will continue to follow the latest nightly.
- The plugin runs with the permissions of the current DSH process. Check the source code and license before installing. The license is MIT, and the repository is publicly accessible. The README indicates compatibility with
dshReleases: 0.2.1-rc.5.
Ending¶
What dsh-staging-hunter does is narrow: it understands the hash bucketing of electron-updater staging, then uses a persistent low-order UUID and file guarding to pin the local machine to the first batch. It is suitable for those who clearly want to follow the nightly builds; if you don’t want to, there’s no need to install it.
Directory: https://www.skillhub.cn/plugins/ChenXu233/dsh-staging-hunter
GitHub: https://github.com/ChenXu233/dsh-staging-hunter