JetBrains / JetBrains/thinkrail
Desktop typecheck (and the pre-commit hook) hangs while `electrobun dev` runs (after upgrading Electrobun to 2.0.1)
- Dominant language
- TypeScript
- Stars
- 467
- Forks
- 37
- Avg merge
- 1d 52m
- Merged PRs (30d)
- 143
Description
## Description
`bun run typecheck` never finishes while `electrobun dev` is running in the same worktree, so the
husky pre-commit hook hangs and no commit can be made without stopping the desktop dev host first.
`@thinkrail/desktop`'s typecheck is `electrobun prepare && tsc --noEmit`. `electrobun prepare` takes
Hutch's exclusive project build lock (`apps/desktop/.hutch/locks/electrobun-build.lock`) *before*
deciding it has nothing to do, and `electrobun dev` holds that lock for its entire run. Since the
projection under `.hutch/devkit` is already valid in that situation, the wait buys nothing.
Hutch offers no bypass: `HUTCH_ELECTROBUN_BUILD_LOCK` is its recursion guard, not an escape hatch —
setting it makes `prepare` exit with `RecursiveElectrobunBuild`.
## Steps to reproduce
1. `cd apps/desktop && bun run dev` (leave the Electrobun dev host running)
2. In another shell, from the repo root: `bun run typecheck`
3. Or equivalently, make any change and `git commit` — the pre-commit hook reaches
`@thinkrail/desktop:typecheck: $ electrobun prepare && tsc --noEmit` and stops there.
## Expected behavior
Typechecking the desktop package succeeds while the dev host runs. Preparing an already-valid devkit
projection should not need the exclusive build lock.
## Actual behavior
`turbo run typecheck` blocks indefinitely at `@thinkrail/desktop`. `ps` shows the parked child:
```
node .../apps/desktop/node_modules/.bin/electrobun prepare
.../hutch-engine electrobun prepare
```
It resumes the moment `electrobun dev` is stopped.
## Potential fix
Only call `electrobun prepare` when the projection is not already prepared for the pinned Electrobun
version. `.hutch/devkit/.complete` records exactly that:
```
schema=1
electrobun=2.0.1
target=macos-arm64
source-manifest-sha256=e7978b03...
```
So a small `apps/desktop/scripts/prepare-devkit.ts` that compares that marker against
`devDependencies.electrobun` and shells out to `electrobun prepare` only on a miss, with
`"typecheck": "bun scripts/prepare-devkit.ts && tsc --noEmit"`, keeps fresh machines and version
bumps working while making the common case a no-op. Measured here: desktop typecheck goes from
never finishing to 2.6s with the dev host up.
The other half belongs upstream in Electrobun/Hutch: `prepare` could validate the projection before
taking the lock, take a reader lock on the no-op path, or grow an explicit "skip if current" flag.
Happy to file that separately.
## Environment
- OS: macOS 26.6.2 (arm64)
- Bun version (`bun --version`): 1.4.0
- Node version (`node --version`): v26.8.1
- ThinkRail version / commit: a2cd8c5c
- Electrobun: 2.0.1 (the hang appeared with the 2.0.1 / Hutch migration; it did not happen before)
---
🤖 Filed by Claude (via Claude Code) on behalf of @CommanderTvis
Contributor guide
Research direction
Start with apps/desktop/package.json, the typecheck command, and apps/desktop/.hutch/devkit/.complete; compare the marker’s pinned Electrobun version and target with the desktop dependency. Then inspect the existing Electrobun scripts and run bun run typecheck while electrobun dev is active. Done means typecheck completes without waiting on the dev host, while fresh projections and version changes still prepare successfully.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bun, typescript
- Domain
- build-system, desktop, developer-experience
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100