Preface¶
If you use the DSH (DeepSeek Harness) desktop client for a long time, you might encounter a slightly scary error at startup: desktop welcome: Web authentication failed. Reinstalling the client won’t help. The root cause of this error is not the account, but the local cookie database: every time the host starts, it picks a random port, and the authentication cookie name includes host:port. When the port changes, a new entry is added. As entries pile up, they eventually burst the HTTP request header limit, the server returns 431, and the client attributes it to an authentication failure.
The plugin introduced below, dsh-cookie-cleaner (maintainer drscrewdriver, category admin-security), is designed to handle this: it can read-only report on the accumulation of local dsh-auth-* entries, and use a separate command to clean them up after the client has fully exited. Compared to “asking AI how to clean every time,” it solidifies the causal chain, platform library locations, and security boundaries within the tool.
What is this¶
One-sentence positioning: A DSH plugin + an independent cleaning command distributed with the package, aiming to solve the startup failure issue “HTTP 431 definitely appears after about 70 random port startups” of the desktop client.
- Maintainer: drscrewdriver
- Version: 0.2.1 (from package.json)
- License: MIT
- Runtime Environment: Node ≥ 22.19 (uses
node:sqlite; Electron 44’s built-in Node 24 also works)
The plugin itself never writes to the database: the cleanup action can only happen during the time window when the client has fully exited, but the host plugin itself does not exist at that moment. Therefore, the plugin mainly does read-only reporting and command guidance; the actual execution body is src/cli.js in the package. Separating the two designs is the prerequisite for understanding its usage.
Core Features¶
First, a design trade-off: Reading and cleaning are two independent paths. The panel and command interface will first try to open the cookie database in read-only mode (readOnly). If successful, they provide real-time values—entry count, request header byte usage, percentage usage, and how much is left before 431; if not, they explicitly say “cannot read,” they won’t turn “not read” into “0 entries”. Cleaning must wait until the client exits and is executed by a separate script.
There are four specific capabilities:
- Runtime Reading. When the client is running, on Windows, it can take a snapshot reading by borrowing the host process’s already-open handle (only Windows, non-win32 falls back to a busy loop); the borrowed result comes with
snapshot:true, and the panel will separately mark it as “non-real-time”. The snapshot has a budget limit:OpenProcessonly once per PID, default limit 20,000 attempts / 1200ms, exceeding it reportsscan-budget. - Read-only Reporting Command
/cookie-cleaner(statusorclean), outputs current statistics, and provides a cleaning command that can be copied and executed directly. - Profile Patch Health Check & Repair
/cookie-cleaner patch(check/fix/revert/plan), replaces manual checks of the profile’scordis.patch.ymlwith machine determination, and provides one-click repair (validated against Config schema before writing, auto-rollback on failure). - Independent Cleaning CLI, supports three modes: full delete, expired-only, and dry-run. Backs up before writing; the delete statement consists only of
host_keywhitelist + name prefix.
Security measures taken during cleanup are worth listing separately:
- Copy
.bak-<timestamp>before writing to disk; if the main database copy fails, the whole transaction is aborted (all-or-nothing); - Take along
-wal/-shm/-journalsidecars; if a sidecar fails to copy, it is only logged as skipped; - Refuse execution if exclusive write lock
BEGIN IMMEDIATEcannot be obtained, and provide corresponding handling text for that level; - Refuse if there is no
cookiestable or missing critical columns in the database; never execute write statements on unknown databases.
These cookies do not affect login and do not involve account credentials: Main window requests use in-memory credentials and do not go through the cookie jar; every startup re-issues using a launch token. What is deleted are just local historical residues.
Installation¶
Install as a DSH plugin and install the cleaning tool globally:
# As a DSH plugin (provides /cookie-cleaner read-only reporting)
dsh --profile desktop plugin add dsh-cookie-cleaner
# The cleaning tool is distributed with the package; after installation, you can use the alias in the profile or type the command directly after global installation
npm i -g dsh-cookie-cleaner
Note one point: The desktop profile is managed by the client itself; the command line dsh plugin add might be rejected, reporting profile "desktop" is managed exclusively by the Electron application. In that case, install it in the client’s plugin management interface. The cleaning script itself is independent; it can run whether globally installed via npm or via node <package directory>/src/cli.js, and does not depend on the host loading it.
Alias path after installing into profile:
# Windows
%USERPROFILE%\.dsh\profiles\desktop\node_modules\.bin\dsh-cookie-cleaner.cmd
# macOS / Linux
~/.dsh/profiles/desktop/node_modules/.bin/dsh-cookie-cleaner
Typical Usage¶
The two-step order of the cleanup action is fixed: First confirm the client has fully exited, then run the cleanup. First, look at common parameters:
dsh-cookie-cleaner View current status: where is the library, how many dsh-auth-* entries, how many are expired
dsh-cookie-cleaner --clean Delete all dsh-auth-* entries under the loopback domain (127.0.0.1/localhost/[::1])
dsh-cookie-cleaner --clean --expired-only Conservative mode: delete only expired ones
dsh-cookie-cleaner --clean --dry-run See how many entries will be deleted without writing to disk
dsh-cookie-cleaner --db=<full path> Manually specify the cookie database
dsh-cookie-cleaner --lang=de Specify output language (defaults to system locale)
Exit code: 0 success; 1 failure (locked / no permission / not found / invalid arguments). It is recommended to dry-run before deleting.
Exit the client differently on each platform, and the cookie database default location is also different:
# Windows: Tray → Exit; confirm no residual processes
Get-Process | Where-Object { $_.ProcessName -match 'DeepSeek|dsh' }
# Library location: %APPDATA%\@deepseek-ai\dsh-desktop\Network\Cookies
dsh-cookie-cleaner --clean --dry-run
dsh-cookie-cleaner --clean
# macOS: Cmd+Q; Dock icon disappearing doesn't mean exited
ps aux | grep -i '[D]eepSeek Harness'
# Library location: ~/Library/Application Support/@deepseek-ai/dsh-desktop/Network/Cookies
dsh-cookie-cleaner --clean --dry-run
dsh-cookie-cleaner --clean
# Linux: Close main window and confirm
pgrep -af 'DeepSeek Harness|dsh-desktop'
# Library location: ~/.config/@deepseek-ai/dsh-desktop/Network/Cookies (XDG_CONFIG_HOME takes priority)
dsh-cookie-cleaner --clean --dry-run
dsh-cookie-cleaner --clean
# Only delete expired ones:
dsh-cookie-cleaner --clean --expired-only
When no global command is installed on macOS, run the script inside the package directly:
node ~/.dsh/profiles/desktop/node_modules/dsh-cookie-cleaner/src/cli.js --clean
Successful output looks like this, with the number of deleted entries, database size change, and backup location included:
Deleted 3 dsh-auth-* entries (all)
Database: ~/.config/@deepseek-ai/dsh-desktop/Network/Cookies 20480 B → 8192 B
Backup: ~/.config/@deepseek-ai/dsh-desktop/Network/Cookies.bak-20261104-061512 (incl. -wal, -shm)
Account credentials, sessions and plugin configuration were not touched; the local cookie is re-issued on next start.
About the root cause of the pile-up: The host uses a random port every startup (the host startup argument in apps/desktop-host/src/index.ts is --port 0), and the authentication cookie name is dsh-auth- + base64url(sha256(authority)). Under HTTP, authority takes url.host (including port); RFC 6265 does not isolate cookies by port, so all historical port entries under 127.0.0.1 are sent together. One entry is about 229 B, Node’s default --max-http-header-size is 16384, 16384 / 229 ≈ 71.5, meaning it will definitely fail after about 70 startups. Upstream already has three independent discussion reports pinned to the same causal chain (#11366, #11410, #11650). Reducing connection.cookieMaxAgeDays (shortening cookie lifetime) is the only item the panel actually “fixes”; fixing webserver.port belongs to the startup behavior aspect and is only retained in the command aspect.
Applicable Scenarios and Notes¶
Suitable people: Developers using the DSH desktop client, especially users who have installed version rc.2 or later and have encountered desktop welcome: Web authentication failed; as well as profile maintainers who want to reduce pile-up from the source and are willing to modify the profile. The plugin side provides settings userDataRoot, expiredOnly, lang, guardDays, guardMode. The browser card is located in the top-level section “Cookie Cleaner” of the settings page and the configuration card of the plugin page, providing three buttons: Health Check / Repair / Revert. Output supports 9 languages, following system locale (neutral locales like LANG=C.UTF-8 / POSIX are judged as English), unrecognized languages fall back to zh.
A few notes:
- The plugin runs with the current dsh process permissions. The cleanup action requires the client to have fully exited, otherwise it will be rejected as occupied (bundled Windows handle snapshot read-only capability is not included here, and is only for Windows).
- The community directory site is an independent site, with no official affiliation to DeepSeek / Fenxiang. This plugin is maintained by a third party. It is recommended to check the source code and license (MIT) before installation to ensure compatibility with your environment.
- The CLI’s health check function only sees the file layer in offline mode; comparing runtime and bundle layers requires the client to be up and checked by the panel or
/cookie-cleaner patch check. The CLI never writes to the profile; writing configuration is only done by the host side’s path with validation and rollback. - Linux users note that neutral locales like
LANG=C.UTF-8will get English output; use--lang=zhexplicitly if Chinese is needed.
Summary¶
The value of this plugin lies not in “having one more cleaning script,” but in it locating, quantifying, and safely cleaning a difficult self-diagnosed problem (random ports cause cookie names to change with ports, pile up, and eventually cause 431), while not touching account credentials, sessions, and plugin configuration. For users who have already hit 431, dry-running before real deletion is a very low-cost verification path.
Directory page: https://www.skillhub.cn/plugins/drscrewdriver/dsh-cookie-cleaner
GitHub: https://github.com/drscrewdriver/dsh-cookie-cleaner