>_SUMMARY
zwire is a Chromium/Blink browser forked into a keyboard-driven cyberpunk HUD. The bulk is the HUD workspace (extensions/hud-internal, ~11,800 LOC) — the ztmux tiling overlay (tmux-style panes/windows, each an embedded webview; rebindable prefix; partial synchronize-panes; durable session CRUD), a ⌘K command palette, vim navigation, a find bar, a status bar, the 8-scheme picker, a browser-wide audio EQ + live meters, and 22 HUD pages. Under it, the source fork removes the theme-extension ceiling — a Chrome theme changes colors only, so the native tab shape, UI font, and toolbar can't be reached from an extension — by compiling a patched Chromium: a 25-patch series authored against tag 150.0.7871.46 and verified apply-clean. This is what zwire ships as. The counters below are read from the patch files and the tree at commit 97de26164a; each per-patch "approach" is condensed from fork/patches/README.md, whose anchors were verified against the target file at that exact tag. Apply-clean proves the diff context matches the pinned source; it does not prove the C++ compiles — fork/build.sh is that gate.
#HUD PATCH SERIES
Applied in order by fork/apply-patches.sh, reversible with --reverse. Each patch was authored by reading its target file at the exact tag on the Chromium GitHub mirror (raw.githubusercontent.com/chromium/chromium/150.0.7871.46/…) — not fabricated blind — and verified apply-clean with git apply --check. Hunk and byte counts are computed from the patch files; the approach column is condensed from fork/patches/README.md. The radius-calc, color-mixer, toolbar Init, and ComputeBorderRadius anchors shift between Chromium milestones, so most releases need a re-anchor — that is the ongoing solo-fork cost.
| Patch | Target file(s) · anchor | Hunks | Bytes | Approach |
|---|---|---|---|---|
0001-tab-shape-hud.patch | tabs/tab_style_views.cc · GetPath | 4 | 7,405 | Replace the rounded-rect tab path with a hard trapezoid — straight sloped sides (hud_slope = (bottom - top) * 0.28), sharp top corners — for the classic-Chrome silhouette; the kInteriorClip / kHitTest paths stay rectangular so the favicon and title are never clipped. |
0002-ui-colors-hud.patch | color/chrome_color_mixer.{cc,h} color/chrome_color_mixers.cc · AddChromeColorMixer | 6 | 18,431 | Force the cyberpunk palette + the 8 HUD Sys-token schemes onto frame / toolbar / tab bg+fg / omnibox and recolor the under-toolbar separator neon cyan, before the high-contrast early-return; ends with AddZwireHudFinalMixer (dead-last) re-asserting tab colors so the Material/native tab-strip mixers can't leave the active tab a scheme-independent default. Beyond what a theme extension can reach. |
0003-ui-font-mono-hud.patch | resource/resource_bundle.cc · InitDefaultFontList | 1 | 932 | Set gfx::FontList::SetDefaultFontDescription("Share Tech Mono, Monaco, 13px") so all native chrome UI text renders in the HUD mono face, Monaco as a guaranteed-present fallback. |
0004-toolbar-neon-border.patch | toolbar/toolbar_view.cc · Init | 2 | 1,073 | Add a 2px cyan bottom border via views::CreateSolidSidedBorder(…, kColorToolbarContentAreaSeparator); the separator color itself is set neon cyan in 0002. |
0005-omnibox-hud.patch | location_bar/location_bar_view.cc · ComputeBorderRadius | 1 | 769 | Clamp the field radius to 2px so the omnibox is the sharp HUD field instead of the rounded pill; background + border come from 0002. |
0006-branding-strings.patch | chrome/app/theme/chromium/BRANDING | 1 | 903 | Chromium → zwire product names, MenkeTechnologies company, com.menketechnologies.zwire bundle id — the file the unbranded (is_chrome_branded=false) build reads. |
0007-devtools-hud-theme.patch | front_end: design_system_tokens.css entrypoints/main/main-meta.ts ui/legacy/theme_support/ThemeSupport.ts | 4 | 7,267 | Add the 8 HUD schemes to the DevTools Theme dropdown (default zbhud-cyberpunk). ThemeSupport maps zbhud-<scheme> onto the dark base and stamps [data-zbhud]; without it, stock Light/Dark/Auto are untouched. |
0008-allow-framing.patch | renderer_host/ancestor_throttle.cc · WillStartRequest | 1 | 1,546 | Bypass X-Frame-Options / frame-ancestors CSP so the ztmux overlay (extensions/hud-internal/ztmux.js) can iframe any site into its N-pane tiling. Replaces the removed 0008-tmux-split-prefix patch (native 2-pane split), superseded by the JS overlay. |
0009-ext-command-focus-webcontents.patch | extensions/extension_keybinding_registry_views.cc | 2 | 2,315 | When an extension command fires while a chrome UI surface (omnibox/search bar) has focus, hand focus to the page web contents so the ⌘K palette overlay is typeable. |
0010-newtab-force-zwire.patch | browser/search/search.cc · HandleNewTabURLRewrite | 3 | 2,884 | When the zwire new-tab extension is loaded, chrome://newtab always resolves to it instead of the default Google NTP — the new tab is always the HUD. |
0011-pinned-extensions-always-show.patch | toolbar/toolbar_view.cc | 1 | 1,302 | Hold the extensions container at its preferred width so pinned actions never collapse into the puzzle overflow when an extension is re-pinned at runtime. |
0012-allow-frame-src.patch | renderer_host/navigation_request.cc | 1 | 1,039 | A host page's frame-src / child-src CSP never blocks a sub-frame navigation, so the ztmux overlay can embed any site into a pane — complements 0008's frame-ancestors bypass. |
0013-default-restore-last-session.patch | browser/prefs/session_startup_pref.cc | 1 | 863 | Default startup preference = restore the last session, so tabs auto-restore on launch. |
0014-no-session-crashed-bubble.patch | views/session_crashed_bubble_view.cc | 1 | 1,527 | Never show the "Restore pages?" session-crashed bubble — the restore-last-session default (0013) already brings tabs back. |
0015-no-navigation-block.patch | browser/extension_navigation_throttle.cc | 1 | 1,245 | Never block a chrome-extension:// navigation to a not-yet-registered extension, so the new-tab override page always loads at startup before its extension finishes registering. |
0016-ext-private-api-allowlist.patch | extensions/api/_permission_features.json | 3 | 1,593 | Allowlist the hud-internal extension for developerPrivate (widens extension_types to include "extension") + settingsPrivate, so the HUD Extensions / Settings pages get those chrome.* APIs. |
0017-no-hold-to-quit.patch | browser/app_controller_mac.mm · runConfirmQuitPanel | 1 | 1,079 | Force hold-⌘Q-to-quit off (immediate quit) regardless of the kConfirmToQuitEnabled pref a synced profile can flip back on. |
0018-ext-dispatch-null-policy-container.patch | extensions/browser/extension_function_dispatcher.cc | 1 | 1,680 | Gate the is_sandboxed UMA probe on RenderFrameHost::IsActive() so an extension-function IPC from a non-active frame (null policy_container_host_) can't hit a NOTREACHED — fixes the SIGTRAP when a content script calls a chrome.* API on the Web Store mid-navigation. |
0019-ext-script-webstore.patch | extensions/chrome_extensions_client.cc · IsScriptableURL | 1 | 1,366 | Drop the gallery special-case (kCannotScriptGallery) so extension content scripts + tabs.executeScript run on the Chrome Web Store domains; store-privileged JS bindings stay gated by IsWebstoreOrigin. |
0020-hud-native-menu-colors.patch | color/chrome_color_mixer.cc · AddZwireHudFinalMixer | 1 | 2,648 | Bind the ui::kColorMenu* family (app / three-dot / context menus, dropdowns) to the HUD Sys tokens so native Views menus follow the scheme + light/dark toggle instead of the NativeTheme default. References, not literals — depends on 0002's Sys-token block. |
0021-hud-native-primitive-colors.patch | color/chrome_color_mixer.cc · AddZwireHudFinalMixer | 1 | 1,943 | Rebind every core native-Views primitive (kColorPrimary/Secondary, backgrounds, midground) to the HUD-mode-aware Sys tokens so dialogs / bubbles / textfields / tooltips track HUD light/dark + scheme in one place instead of inverting when HUD and OS modes disagree. Generalizes 0020. |
0022-audio-eq-output.patch | services/audio/output_controller.{cc,h} browser/chrome_content_browser_client.cc | 9 | 61,778 | Browser-wide output DSP: a per-stream ZwireAudioEq chain applied in OutputController::OnMoreData() to every output stream before the OS device, so all tab audio (media, MSE/YouTube, Web Audio, WebRTC) is processed. Chain (zdsp-core port): preamp → RBJ-biquad EQ cascade → gain → drive (tanh) → feed-forward compressor → feedback delay/echo → reduced-Freeverb reverb → M/S width → equal-power pan / mono-fold → brickwall limiter. Always-on, live-swappable process-global config (empty = unity passthrough); config forwarded to the sandboxed audio utility as the --zwire-audio-eq switch. |
0023-audio-tab-capture.patch | extensions/api/tab_capture/tab_capture_api.cc extensions/api/_api_features.json | 2 | 2,144 | Let the HUD Audio page pull a playing tab's real output into its analyzer: expose tabCapture to hud-internal without the manifest permission, and default the allowlisted id so getMediaStreamId bypasses the activeTab picker/prompt. Scoped to the one id. |
0024-audio-live-config.patch | services/audio/…/audio_service.mojom services/audio/service.{cc,h} browser/audio/audio_service.cc | 10 | 14,827 | Live, always-on config for the 0022 EQ with nothing open: the unsandboxed browser process polls $STATE/audio-eq and pushes the spec over a new mojom AudioService::SetZwireEqConfig (the audio sandbox can't read the file). Also carries the output-meters back-channel — a compact post-DSP meter frame (spectrum bars + peak/RMS + phase + scope) pumped to the Audio page over the native host on a ThreadPool sequence, off the UI thread so gestures don't starve it. |
0025-hud-native-custom-palette.patch | color/chrome_color_mixer.cc · AddZwireHudFinalMixer | 4 | 5,868 | Read a hud-palette base-colour projection (zwire-host writes it from [theme.palette] as --var=#rrggbb lines) and, when present + complete, paint the native chrome (tab labels/accent, toolbar, omnibox, frame) from those resolved colours instead of the baked 8-entry kHudSchemes name table — so any scheme, built-in or custom (custom-N, absent from the table), paints correctly and the picker no longer needs a matching table name. ReadHudPaletteFile() parses under a lock and repaints on change via the existing dir watcher. Depends on 0002. |
| SERIES TOTAL | 31 unique Chromium files | 63 | 144,427 | All 25 authored & apply-clean at tag 150.0.7871.46. Compile-verify via fork/build.sh (~100 GB checkout, 1–4 hr first build). |
$RUNTIME EXTENSIONS
bin/zwire starts the base against a dedicated $ZWIRE_STATE/profile with --load-extension pointing at newtab + zpwrchrome + hud-internal, and --extensions-on-chrome-urls set (the internal-HUD skin runs on chrome://*/*). Only directories that contain a manifest.json are included, so a missing submodule degrades gracefully. "manifest present" is read from disk; "loaded by launcher" is bin/zwire:40. The theme extension ships in-tree but is deliberately not launcher-loaded — a static Chrome theme applies last and would override the fork's native color mixer (patch 0002) and the internal-HUD skin, so the launcher leaves it out. The hud-internal extension is the workspace layer (~11,800 LOC across 11 subsystems + 22 pages): the ztmux tiling overlay, ⌘K palette, vim nav, find, status bar, session CRUD, the 8-scheme picker (with light/dark toggle), and the Audio dashboard, persisted via chrome.storage and bridged to a native host (native/zwire-host).
| Directory | Manifest name | manifest present | loaded by launcher |
|---|---|---|---|
newtab | zwire New Tab | yes | yes |
extensions/zpwrchrome | zpwrchrome | yes | yes |
extensions/hud-internal | zwire HUD Internal | yes | yes |
theme | zwire Cyberpunk | yes | no |
@WHY A REAL BLINK BASE
zpwrchrome is a Manifest V3 extension needing userScripts, declarativeNetRequestWithHostAccess, nativeMessaging, webRequest, a service-worker background, and minimum_chrome_version: 127 — capabilities that run only on a genuine Chromium engine, not WebKit (Tauri/Safari) or Servo. The fork compiles unbranded (is_chrome_branded=false): no Google logo, no "for automated testing" banner (that stripe is exclusive to Chrome for Testing). A Chromium build also keeps the --load-extension switch that preloads zpwrchrome, removed from branded Chrome in v137. The unbranded release is installed as the zwire base (base.path) and pinned tag recorded in base.version for the launcher.
The native fork
The HUD workspace is extension code, but an extension can't reach the native chrome — tab shape, UI font, toolbar are C++. So zwire is compiled from a Chromium source fork: whole-chrome restyling that a theme extension can't do. It pays for that with a ~100 GB checkout, ~150 GB disk, a 1–4 hr first build, and rebasing fork/patches/ onto each tracked Chromium release — the maintenance trap that keeps Brave and ungoogled-chromium team-sized. No paid infra is needed, but it exceeds stock GitHub-hosted runners (checkout > disk; cold build > the 6 h job cap), so it builds locally or on a self-hosted runner with a warm checkout.