* Support scroll on linux
* Close tab on middle-click of the X button too
The X icon only had onClick, which browsers never fire for the middle
button. Wire it to the same middle-click handler already used on the
tab body so middle-clicking the X closes the tab like clicking
anywhere else on it does.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Spawn shell via flatpak-spawn --host on Flatpak builds
The Flatpak build sandboxes the shell inside the app's mount namespace,
so PATH ends up as whatever the runtime provides (/app/bin:/usr/bin)
with no access to /usr/local or /home/linuxbrew, unlike an unsandboxed
terminal like Konsole. Route the pty through flatpak-spawn --host so
the shell actually runs on the host and its --login profile computes a
normal host PATH, and grant the org.freedesktop.Flatpak talk-name the
portal needs for this.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Document Flatpak shell-spawning fix and bare-shell-name limitation
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Fix prettier lint in session.ts and tabs.tsx
Both fit within the 120-column print width, so prettier wants them on
one line.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* chore(updater): switch auto-update feed to Quine Global endpoint using query parameters
The client now calls https://hyper.quineglobal.com/update (and /api/update-check)
with query params instead of the old releases.hyper.is / releases-canary.hyper.is
subdomain paths.
- Uses platform, arch, version, and channel parameters.
- Supports explicit channel=canary so users on stable builds can still opt into
canary updates via config.
- Pairs with corresponding server-side changes in hyper-quineglobal-com.
* Fix prettier
Duplicate @types/react TypeScript error (package.json, pnpm-lock.yaml)
What: Added "pnpm": { "overrides": { "@types/react": "18.3.12" } } to the root package.json.
Why: @types/react-dom@18.3.1, @types/hoist-non-react-statics, and @types/styled-jsx all declare @types/react:
"" as a plain dependency. With yarn this was resolved by the resolutions field. With pnpm, resolutions is
ignored — pnpm only reads pnpm.overrides. Without the override, each of those packages resolved "" to the
latest @types/react@19.1.2 and nested it under their own node_modules/. TypeScript then saw two incompatible
definitions for the same React types simultaneously, producing the TS2344: Type 'C' does not satisfy the
constraint 'ComponentType' error in react-redux/es/types.d.ts.
The nested @types/react@19.1.2 directories were also stale artifacts from pre-override installs — pnpm's
--force flag reinstalls packages but does not scrub orphaned nested node_modules subdirectories. They were
removed manually, and the pnpm.overrides prevents them from reappearing on future installs.
Cannot find module 'execa' crash at app startup (app/package.json, app/session.ts)
What: Upgraded shell-env from 3.0.1 to 4.0.3, added execa@5.1.1 as a direct app dependency, removed
os-locale@5.0.0, replaced its one usage with Intl.DateTimeFormat().resolvedOptions().locale, and updated the
shellEnv.sync() call to the new named export shellEnvSync.
Why: This was a layered problem rooted in how electron-builder packages the app when using pnpm.
electron-builder builds the asar by walking pnpm's flat (hoisted) node_modules dependency tree. When two
packages need incompatible major versions of the same dependency, pnpm cannot hoist both — it puts the
minority version in a nested node_modules/ inside the requiring package's directory. electron-builder's pnpm
integration only scans the flat level; it emits "dependency not found on disk" for anything nested, and those
nested packages are silently excluded from the asar.
shell-env@3.0.1 needed execa@^1.0.0. The hoisted top-level was execa@4.1.0. So pnpm nested execa@1.0.0 under
node_modules/shell-env/node_modules/execa/. electron-builder missed it. At runtime, require('shell-env') →
require('execa') → crash, even on macOS where the shellEnv.sync() call is never actually reached (the import
itself triggers the error).
Upgrading shell-env to 4.0.3 alone would have just shifted the nesting from execa@1 to execa@5 (since 4.0.3
uses ^5.1.1). And os-locale@5.0.0 used ^4.0.0, which would then become the nested one instead. There is no
version of either package where both use the same execa major, so they can't both be hoisted simultaneously.
The fix makes execa@5.1.1 the explicit top-level dependency. shell-env@4.0.3 (needs ^5.1.1) is satisfied
without nesting. os-locale is removed entirely and its one call site replaced with
Intl.DateTimeFormat().resolvedOptions().locale, which returns the same locale string from a V8 built-in — no
execa chain at all.
CI frozen-lockfile failure inside electron-builder install-app-deps (app/.npmrc)
What: Added frozen-lockfile=false to app/.npmrc.
Why: target/ is the electron-builder app directory and is fully gitignored. That means target/pnpm-lock.yaml
is never committed. In CI, pnpm automatically enables frozen-lockfile=true when it detects CI=true in the
environment — this applies to every pnpm invocation in the process tree, including child processes.
The postinstall sequence is: webpack copies app/ to target/ → electron-builder install-app-deps runs pnpm
install inside target/. Because app/.npmrc contains ignore-workspace=true, pnpm treats target/ as a standalone
project rather than part of the workspace, and looks for a target/-local lockfile. On a fresh CI checkout
there is none. With frozen-lockfile=true inherited from the CI environment, pnpm refuses to generate one and
exits with ERR_PNPM_OUTDATED_LOCKFILE.
Locally this was invisible because target/pnpm-lock.yaml accumulated from previous runs and was simply reused.
Adding frozen-lockfile=false to app/.npmrc (which webpack copies to target/.npmrc) overrides the CI
environment default specifically for the target/ context, allowing pnpm to generate a fresh lockfile on each
CI run.
app/session.ts locale — removal of os-locale
Already covered under point 2, but worth noting separately: osLocale.sync() was the only call site.
Intl.DateTimeFormat().resolvedOptions().locale is a direct replacement — it returns the OS locale (e.g. en-US)
in the same format, available in all modern Node/Electron versions with no external dependencies. The
.replace(/-/, '_') transforms it to POSIX LANG format (en_US) exactly as before.
* Add troubleshooting
* fix(cli-install): lazy-require native-reg to fix TS error on non-Windows
native-reg is a Windows-only optional dependency that can't be resolved
at compile time on macOS/Linux. Move the require() inside addBinToUserPath
and add an explicit platform guard that rejects early before the Promise
is constructed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore(deps): pin electron-link to quine-global v0.7.0
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix devtools patch
* Fix type error
* fix(snapshot): avoid npm_config_arch polluting node-gyp-build on cross-arch builds
electron-link depends on classic-level (via node-gyp-build), which reads
npm_config_arch to select its native prebuild. Setting npm_config_arch=arm64
on an x64 host caused it to dlopen the arm64 .node binary, crashing the
v8 snapshot build. Switch to a dedicated SNAPSHOT_TARGET_ARCH env var that
only mk-snapshot.js and cp-snapshot.js read, keeping npm_config_arch unset.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix type error
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix macOS 26 GPU performance issue by upgrading to Electron 38
Upgrades Electron from 34.5.1 to 38.6.0 to resolve excessive WindowServer
GPU usage on macOS 26 (Sequoia). This issue was caused by Electron's
override of the private _cornerMask API, which forced the compositor to
treat window masks as dynamic rather than static, resulting in persistent
high GPU load.
Changes:
- Upgrade electron: 34.5.1 → 38.6.0
- Upgrade electron-mksnapshot: 34.5.1 → 38.6.0
- Upgrade @electron/rebuild: ^3.7.1 → ^3.7.2
- Upgrade node-abi: ^3.67.0 → ^3.81.0 (required for Electron 38 support)
The fix was introduced in Electron 36.9.2, 37.6.0, 38.2.0, and all later
versions. We're upgrading to 38.6.0 as it's the latest stable version
compatible with Node 20.11.0.
Fixes: electron/electron#48376
* Use optional chaining
Signed-off-by: Philip Peterson <1326208+philip-peterson@users.noreply.github.com>
---------
Signed-off-by: Philip Peterson <1326208+philip-peterson@users.noreply.github.com>
Co-authored-by: Philip Peterson <1326208+philip-peterson@users.noreply.github.com>