| name | rudder-desktop-dev-recovery-maintainer |
| description | Use when Rudder local Desktop development, Electron shell, embedded Postgres, ~/.rudder instance state, dev startup, update/install smoke, packaged boot, or release-blocking local Desktop validation fails or needs recovery. |
Rudder Desktop Dev Recovery Maintainer
Use this skill to get the local Rudder Desktop development path back to a known
working state.
This is not the release runbook. It is the recovery layer for local Desktop
startup, dev-shell runtime, embedded database state, update/install smoke, and
the handoff point before release work.
Use When
Use this skill for prompts like:
- "
pnpm dev 好像桌面端跑不起来了"
- "Desktop dev shell 起不来"
- "API 能访问,但桌面端没起来"
- "
pnpm dev starts the API but Electron exits during a UI build/typecheck"
- "embedded Postgres /
~/.rudder 状态是不是乱了"
- "update 最新版失败,先 debug 一下"
- "桌面端问题修完之后再发版"
- "我本地 Desktop 是不是指到错的 instance"
Also use this when a release request is blocked by local Desktop validation.
Fix the local Desktop blocker first, then route the release to
release-maintainer.
Do Not Use When
Do not use this skill for:
- npm/GitHub Release/tag/dist-tag publishing; use
release-maintainer
- packaged-app verification after code changes with no startup failure; follow
the normal Desktop validation workflow
- stopping only a known repo-local dev runtime; use
stop-rudder-dev-maintainer
- ordinary web UI data diagnosis; use
rudder-data-path-diagnostician-maintainer
- review-only of a Desktop feature; use
agent-work-reviewer-maintainer
If the user's first request is "发版" and Desktop is already healthy, do not
route through this skill.
Default Workflow
1. Classify the failure mode
Start with a short state packet:
git status --short --branch
- requested command, for example
pnpm dev, pnpm desktop:dev, or
pnpm desktop:verify
- whether the failure is API server, Vite middleware, Electron shell, embedded
Postgres, UI build/typecheck, packaged smoke, update download, or app launch
- exact stderr/stdout excerpt and exit code
- currently listening ports around
3100
- relevant
~/.rudder/instances/* path when the process prints one
- whether the failing file is committed, modified, untracked, or part of a
broader dirty feature set
Do not guess from memory when the command can be rerun safely.
2. Read the local Desktop contract
Read only the relevant docs and scripts:
doc/engineering/DEVELOPING.md
doc/engineering/DESKTOP.md
doc/README.md for navigation when needed
desktop/package.json
- root
package.json scripts
desktop/scripts/smoke.mjs for packaged-smoke expectations
scripts/prod-desktop.mjs only when the failure is prod-local or installer
related
When docs and scripts disagree, scripts are the executable truth for the active
diagnosis. Record the mismatch as a docs follow-up if it matters.
3. Verify the active runtime before repairing
Check the local server and org list when the API is expected to be running:
curl -sS http://127.0.0.1:3100/api/health
curl -sS http://127.0.0.1:3100/api/orgs
If the Desktop shell is pointed at another base URL, use that URL instead.
Common causes to distinguish:
- no server process is running
- wrong port or stale process owns the port
- embedded Postgres failed to initialize
- dev server is up but Electron did not launch
- Electron launched but cannot reach the server
- API/server is healthy, but Desktop launch is blocked because
@rudderhq/ui
build/typecheck fails on dirty WIP, incomplete fixtures, or an untracked
companion feature file
- Desktop profile or instance id points to unexpected data
- update metadata resolves but asset download/checksum/install fails
- update helper or CLI child process writes progress after its parent pipe is
closed, causing
EPIPE, ERR_STREAM_DESTROYED, broken pipe, or an Electron
main-process error dialog during restart
- packaged smoke differs from dev-shell behavior
4. Repair narrowly
Prefer the smallest repair that matches the cause:
- stop only the repo-local stale process when it blocks the port
- reinstall dependencies only when package state or lockfile evidence points
there
- fix script/config code when the failure is reproducible from a clean command
- for dirty-WIP compile failures, build a changed-file ownership packet before
editing: failing path, related untracked files, likely source session or
feature group, and whether a narrow fixture repair would leave a companion
feature half-committed
- reset
~/.rudder/instances/dev only when the user accepts data loss or the
instance is disposable and the task explicitly targets dev state
- keep release publishing untouched until local Desktop state is green
Do not delete ~/.rudder, change npm auth, move GitHub dist-tags, or install a
new app globally as a "dev recovery" shortcut.
If the compile blocker belongs to a larger unrelated feature already dirty in
the worktree, fix only the minimum needed to unblock the requested dev run, and
do not commit a lone companion file unless the whole feature group is in scope.
If a safe narrow repair is not possible, report the ownership packet and the
exact blocked command instead of sweeping unrelated WIP into the recovery.
5. Validate the right path
Validation depends on what failed:
- dev server/API: health and org API calls
- Desktop dev shell: launch evidence plus logs that the shell reached the API
- dirty-WIP compile failure: rerun the failing package build or typecheck and
the original startup command far enough to prove the blocked layer has moved
- packaged startup, profile isolation, migrations, installer assets, or
prod-local data path:
pnpm desktop:verify
- update/download path: dry-run is not enough when the issue is download,
checksum, extraction, or launch; run the strongest safe non-dry-run local
check available and state platform limitations
- update restart path: if the failure appears after clicking "Restart to
update", reproduce or simulate the pipe lifecycle. Check the old app process,
update child process, progress JSON/stdout/stderr handling, installed app path,
and whether the child handles closed output streams as a normal shutdown case.
If code changed, run the narrow relevant tests first, then the repo baseline
when feasible:
pnpm -r typecheck
pnpm test:run
pnpm build
For Desktop startup, migration, profile routing, or packaging changes, do not
claim done without packaged verification or an explicit blocker.
Closed Progress Pipe / Update Child Recovery
Use this branch when the UI update flow starts a helper process or CLI mode and
the error appears after the parent app exits or restarts.
Evidence to collect:
- installed app path, for example
/Users/zeeland/Applications/Rudder.app
- exact update action clicked: automatic prompt, About check, download, or
"Restart to update"
- old version, target version, and whether the app reopened
- stderr/dialog text including
EPIPE, ERR_STREAM_DESTROYED, write after end, broken pipe, or uncaught exception text
- code paths that write progress JSON, flush stdout/stderr, or install/relaunch
the app
Repair pattern:
- Treat closed stdout/stderr/progress pipes during update handoff as expected
when the parent app has exited.
- Add a shared broken-pipe predicate rather than scattering string checks.
- Guard process-level
uncaughtException and unhandledRejection only for
known broken-pipe shutdown errors; do not swallow arbitrary exceptions.
- Add a regression test that closes or destroys the progress reader before the
helper writes/flushed output, and assert the update path exits quietly or
reports success as appropriate.
- Finish with packaged or installed-app verification. If a full in-app update
drill is too expensive, state that limitation and provide the strongest local
substitute plus the exact remaining manual drill.
6. Handoff or escalate
If the user also asked to release after recovery:
- finish the local Desktop repair
- record validation evidence
- route the release portion to
release-maintainer
Keep the handoff concrete:
Root cause: ...
Repair:
- ...
Validation:
- ...
Next route:
- release-maintainer for version ...
Common Failure Modes
- Treating local
pnpm dev breakage as a release problem before reproducing the
local command.
- Resetting
~/.rudder too early and losing the user's useful local state.
- Looking only at API health when the Electron shell is the broken layer.
- Looking only at Electron logs when embedded Postgres never started.
- Claiming update install is fixed from a dry-run that never downloads or
launches the app.
- Treating
EPIPE during update restart as a generic release failure before
checking whether the parent progress pipe intentionally closed.
- Treating a dirty-WIP TypeScript or fixture failure as Desktop/Postgres
corruption just because it surfaced during
pnpm dev.
- Mixing unrelated dirty package changes into a Desktop recovery commit.
Safety Rules
- Preserve unrelated dirty worktree files.
- Do not destroy local Rudder data without explicit authorization.
- Do not publish, tag, move dist-tags, or create GitHub Releases from this
skill.
- Prefer exact command output and log excerpts over guesses.
- If the fix changes Desktop startup, profile routing, migrations, packaging,
or update behavior, require packaged verification before final handoff unless
blocked.