Highlights of this release
- Add Vim mode for keyboard-driven page navigation, including configurable sequences, page-input focus, heading navigation, and accessibility-backed page structure navigation.
- Add the native keyboard-driven Favorites sidebar with search, tag filtering, editing, shortcut assignment, and split-pane opening.
- Migrate existing favorite folder assignments into the tags-first model.
- Improve popup, floating-pane, external-link, standalone omnibox, CEF lifecycle, rendering, input, audio, and WebView cleanup behavior.
- Harden WebKit bridge paths and refresh dependency, packaging, and release metadata.
Changelog
Features
- 482b51e: feat(cef): capture and measure accessibility payloads (@bnema)
- 4e133f4: feat(cef): capture measured accessibility updates per webview (@bnema)
- 804337e: feat(cef): install accessibility handler at wrap time (@bnema)
- 5ea141f: feat(config): add page mode sequence bindings (@bnema)
- d596066: feat(docmodel): add block kind motions (@bnema)
- a171ee0: feat(docmodel): add heading motion foundation (@bnema)
- 2affa97: feat(docmodel): add list motion kind (@bnema)
- 7d43626: feat(docmodel): add paragraph motion kind (@bnema)
- be1f364: feat(docmodel): add section ranges (@bnema)
- ea79ba3: feat(favicon): decode WebP favicons safely (@bnema)
- abd344b: feat(favorites): add keyboard-driven native sidebar (@bnema)
- 4991fbe: feat(favorites): add native bookmark shortcuts (@bnema)
- 5b8fa27: feat(favorites): add native sidebar browser (@bnema)
- 4a7ea51: feat(favorites): add sidebar query seam (@bnema)
- 3857325: feat(favorites): manage bookmarks from sidebar (@bnema)
- adf5a45: feat(input): dispatch page mode key sequences (@bnema)
- 23fc389: feat(input): rename page mode to vim mode (@bnema)
- 4f688ff: feat(page-mode): add configurable vim sequences (@bnema)
- 0c4b1f1: feat(page-mode): add keyboard page navigation (@bnema)
- eca30c1: feat(page-mode): show pending vim sequences in mode toaster (@bnema)
- 3f7ece6: feat(startup): trace first GTK presentation (@bnema)
- d3c8f2e: feat(ui): enable webview accessibility on vim mode entry (@bnema)
- ec8878f: feat(ui): open floating page requests in browser windows (@bnema)
- f52290e: feat(vim): focus first page input (@bnema)
- a11aeca: feat(vim): navigate live headings (@bnema)
- 7d5dafe: feat(vimkeys): add pure sequence grammar (@bnema)
- 0413b8e: feat(vimkeys): parse page mode sequences (@bnema)
- 41ddc34: feat(workspace): route external links by configuration (@bnema)
Bug Fixes
- 5f3e0e8: fix(audio): guard CEF stream lifecycle (@bnema)
- bfd57d4: fix(aur): increment binary package release (@bnema)
- c5ad8c0: fix(benchmarks): report sqlite close errors (@bnema)
- 114ac55: fix(bootstrap): harden development sandbox root (@bnema)
- 5992583: fix(browsing): keep featureless links in floating panes (@bnema)
- 1f4a728: fix(cef): bound accessibility capture retention (@bnema)
- a12a01c: fix(cef): derive visibility from mapped GTK hierarchy (@bnema)
- 1dc7dd4: fix(cef): keep browser canvas white, move anti-flash to presentation layer (@bnema)
- 39cda6d: fix(cef): preserve accessibility lifecycle requests (@bnema)
- 4733629: fix(cef): prevent queued taps from stalling (@bnema)
- 879e5fe: fix(cef): propagate selected runtime to helpers (@bnema)
- 636c556: fix(cef): recover safely after repeated GPU relaunch (@bnema)
- 55dbfae: fix(cef): synchronize effective visibility transitions (@bnema)
- 1ca6e0a: fix(ci): retry Arch package installation (@bnema)
- 7e592a5: fix(ci): satisfy lint for navigation changes (@bnema)
- 6e3936d: fix(cli): name list chrome heights (@bnema)
- 2352786: fix(config): clarify vim sequence timeout (@bnema)
- 3721706: fix(config): migrate favorites sidebar shortcut (@bnema)
- 25c734e: fix(deps): repin puregotk final regression fix (@bnema)
- d685b6e: fix(deps): repin puregotk lazy registration fix (@bnema)
- 2d5e962: fix(deps): update cef2gtk clipboard integration (@bnema)
- be6b7ea: fix(docmodel): return non-nil block snapshots (@bnema)
- 82824ac: fix(engine): disarm popup lifecycle callbacks (@bnema)
- 8e76281: fix(engine): route floating browsing contexts by features (@bnema)
- d921a00: fix(favicon): use upstream purego WebP module (@bnema)
- 2ddb1b2: fix(favorites): address review follow-ups (@bnema)
- 91c19f7: fix(favorites): address sidebar review findings (@bnema)
- 284f18b: fix(favorites): address sidebar review requests (@bnema)
- 8077f20: fix(favorites): harden folder tag migration collisions (@bnema)
- 6c7260d: fix(favorites): harden tag interaction lifecycle (@bnema)
- 142d625: fix(favorites): migrate sidebar shortcut (@bnema)
- 87325b3: fix(favorites): persist shortcut updates (@bnema)
- 7be5016: fix(favorites): preserve shortcuts on metadata updates (@bnema)
- a2631c0: fix(favorites): refresh sidebar after bookmark changes (@bnema)
- 85a20aa: fix(favorites): release dynamic tag callbacks (@bnema)
- 3991a6e: fix(favorites): satisfy persistence lint (@bnema)
- 49e42b7: fix(favorites): satisfy sidebar lint (@bnema)
- ca9c392: fix(hover): fully detach native controller (@bnema)
- 9c48930: fix(hover): schedule debounced focus on GLib (@bnema)
- 7a23056: fix(input): cancel vim sequence state on detach (@bnema)
- 1c59f12: fix(lifecycle): release rebuilt pane and split owners (@bnema)
- 76e12e8: fix(omnibox): always open standalone links in new window (@bnema)
- c1cf747: fix(omnibox): reconcil entry buffer (@bnema)
- 3ad27cd: fix(page-mode): harden scroll scheduling and repeat (@bnema)
- 5b1cfa8: fix(page-mode): harden scrolling and editable focus (@bnema)
- 2b549d6: fix(popup): clean deferred contexts and failure logs (@bnema)
- 47627e6: fix(popup): harden deferred and CEF failure handling (@bnema)
- e37d7f0: fix(popup): preserve failure diagnostics and cleanup (@bnema)
- b95b119: fix(popup): preserve lifecycle and fallback contracts (@bnema)
- 1ee31e6: fix(popup): satisfy routing lint checks (@bnema)
- 9a38c58: fix(popup): tear down unresolved staged views (@bnema)
- 55df320: fix(runtime): harden navigation and browser lifecycle (@bnema)
- 0a69a74: fix(runtime): isolate development environment (@bnema)
- 7fae873: fix(runtime): prevent stack shrinking across CEF callbacks (@bnema)
- 789ddb7: fix(sidebar): refine search and tag controls (@bnema)
- 0f99bd1: fix(sidebar): relax search input padding (@bnema)
- 519071b: fix(split): release tick callback during cleanup (@bnema)
- 1dd2cab: fix(startup): externalize comparison evidence (@bnema)
- 862d933: fix(startup): guard collector output cleanup (@bnema)
- 6949e93: fix(startup): own CEF trace lifecycle (@bnema)
- 0eb3b66: fix(startup): preserve display session for cold runs (@bnema)
- e4b5a97: fix(startup): record first-presentation provenance (@bnema)
- 3bc6123: fix(startup): reserve GTK presentation completion (@bnema)
- ba97260: fix(startup): sanitize presentation evidence (@bnema)
- a948576: fix(startup): scope collector git trust (@bnema)
- ce24e6e: fix(startup): scope trace to accelerated CEF (@bnema)
- 0d8c582: fix(startup): validate timing artifact consistency (@bnema)
- 703eaba: fix(stress): exercise GTK callback lifecycle under load (@bnema)
- 6c6c1d8: fix(ticks): release raw callback slots (@bnema)
- 7c3858b: fix(ticks): release split raw callback slots (@bnema)
- 3df818c: fix(ticks): unref raw callback slots exactly once (@bnema)
- 646bc9f: fix(ui): address external link review findings (@bnema)
- fdb7c64: fix(ui): bind reveal state to webview identity (@bnema)
- c5be254: fix(ui): preserve opener-capable popup fallback (@bnema)
- 3495a30: fix(ui): preserve revealed webviews across rebuilds (@bnema)
- 697b5f3: fix(ui): restore tab bar state after popup rollback (@bnema)
- 9baacd8: fix(ui): serialize webview reveal mutations (@bnema)
- f108dcf: fix(ui): stabilize external link routing checks (@bnema)
- 9484230: fix(ui): suppress omnibox for external panes (@bnema)
- 79c0bb8: fix(ui): synchronize favorites sidebar notices (@bnema)
- ae52164: fix(vim): address mode rename review findings (@bnema)
- dd428b6: fix(vim): align rebased mode identifiers (@bnema)
- 3a00c38: fix(vim): clear heading highlight on mode exit (@bnema)
- fc18cde: fix(vim): cycle inputs and contain reverse focus (@bnema)
- 14d539b: fix(vim): deduplicate highlighted web views (@bnema)
- 4000758: fix(vim): follow theme accent for headings (@bnema)
- 2bdff8a: fix(vim): format rebased native mode changes (@bnema)
- fc65432: fix(vim): handle nil sequence trie (@bnema)
- 8c7ae2b: fix(vim): keep input activation and reverse focus (@bnema)
- 04133a4: fix(vim): pass tab focus keys to pages (@bnema)
- bf7a503: fix(vimkeys): escape legacy binding collisions (@bnema)
- ffef9a9: fix(vimkeys): make canonical grammar unambiguous (@bnema)
- e7d570f: fix(vimkeys): preserve canonical matcher invariants (@bnema)
- c67625f: fix(vimkeys): preserve canonical sequence ownership (@bnema)
- b856ec1: fix(vimkeys): round trip modified hyphen keys (@bnema)
- 3f164d0: fix(vimkeys): round trip modified unicode keys (@bnema)
- c7fcb6d: fix(webkit): harden editable focus lifecycle (@bnema)
- 1ee1a70: fix(webview): harden reviewed bridge paths (#372) (@bnema)
- c053b99: fix: derive collector module provenance (@bnema)
- 7137fd1: fix: invalidate stale split ratio callbacks (@bnema)
- b0266fa: fix: isolate split idle scheduler (@bnema)
- f940181: fix: own GTK global shortcut actions (@bnema)
Performance
Refactoring
- 986803d: refactor(browsing): centralize context routing contracts (@bnema)
- a6c7a7f: refactor(browsing): model floating context host decisions (@bnema)
- e70f71d: refactor(config): share modal action validation (@bnema)
- 830f50b: refactor(docmodel): share strict block motion scan (@bnema)
- 8f314a2: refactor(favorites): complete tags-first cleanup (@bnema)
- ecab2f7: refactor(favorites): migrate folders to tags (@bnema)
- 2ae1fc7: refactor(favorites): remove folder contracts (@bnema)
- 45b8a06: refactor(favorites): simplify usecase to tags (@bnema)
- 965ed59: refactor(favorites): unify native sidebar interactions (@bnema)
- dd1fd2b: refactor(omnibox): keep favorites tags-safe (@bnema)
- cf4e6b2: refactor(popup): isolate source navigation hosting (@bnema)
- 1cda60e: refactor(systemviews): manage favorites with tags only (@bnema)
- cf4e69e: refactor(ui): consolidate external pane routing (@bnema)
- 8b31f32: refactor(ui): make popup host ownership transactional (@bnema)
- 4bafd5c: refactor(vim): finalize navigation boundaries (@bnema)
- c1deb9b: refactor(vim): move navigation request into dto (@bnema)
- d1365c4: refactor(vimkeys): enforce parser invariants (@bnema)
- 69151be: refactor: consolidate reveal state (@bnema)
Documentation
- 6744d8a: docs(changelog): summarize unreleased changes (@bnema)
- 700b5d6: docs(favorites): clarify tag creation control (@bnema)
- 4c9a8b7: docs(favorites): describe native sidebar shortcuts (@bnema)
- c8b70f3: docs(page-mode): align scrolling and mode feedback (@bnema)
- d15a2cb: docs(readme): refresh project presentation (@bnema)
- 0afb76e: docs(vim): document input and heading navigation (@bnema)
Other Changes
- da71e78: Apply go fix updates (@bnema)
- 6dfc9ef: Merge sanitized crash stability history (@bnema)
- 40378d5: Revert "chore(deps): pin puregotk nil-signal fix" (@bnema)
- d4952b4: chore(build): repair vendored baseline (@bnema)
- f972dae: chore(build): track vendored dependency updates (@bnema)
- 1721466: chore(cef): adopt reliable OSR input stack (@bnema)
- 144bb0b: chore(deps): bump actions/checkout (@dependabot[bot])
- 63b6627: chore(deps): bump github.com/pressly/goose/v3 (#361) (@dependabot[bot])
- 902c404: chore(deps): bump purego-cef to v0.14.1 (@bnema)
- 19817e2: chore(deps): bump purego-cef2gtk to v0.9.1 (@bnema)
- 9a7673d: chore(deps): bump the github-actions group with 2 updates (@dependabot[bot])
- c09db9f: chore(deps): bump the github-actions group with 2 updates (@dependabot[bot])
- d64caed: chore(deps): bump the go-dependencies group with 2 updates (#336) (@dependabot[bot])
- 6ad9832: chore(deps): bump the go-dependencies group with 3 updates (#339) (@dependabot[bot])
- 55b9f67: chore(deps): bump the go-dependencies group with 6 updates (#357) (@dependabot[bot])
- 4d548f3: chore(deps): integrate approved upstream foundations (@bnema)
- 8e234aa: chore(deps): integrate cef2gtk presentation synchronization (@bnema)
- 94546f0: chore(deps): pin cef2gtk dmabuf churn (@bnema)
- a161e34: chore(deps): pin puregotk nil-signal fix (@bnema)
- 1a39e17: chore(deps): release cef2gtk v0.8.3 integration (@bnema)
- 04b52b5: chore(deps): release cef2gtk v0.8.4 integration (@bnema)
- bdb7c71: chore(deps): stop tracking vendored modules (@bnema)
- 137c229: chore(deps): update purego audio and sqlite bindings (@bnema)
- aaec84c: chore(repo): keep roadmap evidence out of Git (@bnema)
- e4062c5: chore(systemviews): refresh templ generated headers (@bnema)
- dd6d7a0: chorer: Remove status section from README (@bnema)
- aeeb3f5: merge phase 4 omnibox favorites tags refactor (@bnema)
- b1d9b92: merge phase 5 systemviews favorites tags refactor (@bnema)
- 7351f41: style(cef): satisfy safety marker lint (@bnema)
- 5a776d4: style(hover): format GLib scheduler (@bnema)
- 2624fd3: style(ticks): format callback cleanup (@bnema)
- a347952: test(cef): cover GPU relaunch safety marker (@bnema)
- 2261416: test(cef): cover deduplicated visible sync (@bnema)
- d49b626: test(cef): cover effective visibility transitions (@bnema)
- 04c1bf8: test(cef): require effective mapped ancestor visibility (@bnema)
- 49ad311: test(cef): specify first-presentation hook wiring (@bnema)
- eee76d7: test(cef): specify subprocess runtime propagation (@bnema)
- 55482b4: test(config): cover vim action migration (@bnema)
- 5d1e8c2: test(docmodel): reuse paragraph block kind constant (@bnema)
- 99a0f9c: test(favicon): handle sized PNG decode failures (@bnema)
- 2548d05: test(gtk): require active display for callback stress (@bnema)
- 3737c79: test(hover): cover GLib scheduling lifecycle (@bnema)
- d1de38f: test(hover): require native detach ownership (@bnema)
- 81a8f56: test(pane): cover callback cleanup (@bnema)
- a784a53: test(split): cover tick callback cleanup (@bnema)
- 8b5f874: test(startup): satisfy collector lint (@bnema)
- 4cd14fa: test(startup): specify first-presentation trace transitions (@bnema)
- fba7744: test(stress): require GTK callback lifecycle exercise (@bnema)
- 0650709: test(stress): satisfy GTK stress lint (@bnema)
- 2053bfd: test(stress): satisfy controller cleanup lint (@bnema)
- 7e499de: test(stress): stabilize GTK ledger assertions (@bnema)
- d80cc8e: test(ticks): cover raw callback slot cleanup (@bnema)
- 7b6d57c: test(ticks): require raw callback unref exactly once (@bnema)
- 67cc805: test(ticks): require split raw slot release (@bnema)
- 82da5b8: test(tree): cover split cleanup ownership (@bnema)
- 25599f9: test(ui): cancel transient toaster timers (@bnema)
- 0600fe7: test(ui): clean up deferred toaster callbacks (@bnema)
- 3eb9180: test(ui): cover floating browsing context routing (@bnema)
- 47e07ec: test(ui): cover rebuilt pane reveal state (@bnema)
- 192c70d: test(ui): verify floating popup window ownership (@bnema)
Installation
Linux (x86_64/amd64)
# Download latest release
wget https://github.com/bnema/dumber/releases/latest/download/dumber_linux_x86_64.tar.gz
# Extract and install to ~/.local/bin (enables auto-updates)
tar -xzf dumber_linux_x86_64.tar.gz
mkdir -p ~/.local/bin
install -m 755 dumber_*/dumber ~/.local/bin/
# Ensure ~/.local/bin is in your PATH (add to ~/.bashrc or ~/.zshrc if needed)
# export PATH="$HOME/.local/bin:$PATH"Dependencies
Arch Linux:
# Core CEF, WebKit fallback, and GTK4
sudo pacman -S cef webkitgtk-6.0 gtk4
# GStreamer for WebKit media playback
sudo pacman -S gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav gst-plugin-pipewire pipewire pipewire-pulse
# Optional CEF build with VA-API hardware video decoding
# paru -S cef-vaapi
# Hardware acceleration drivers (choose based on your GPU)
# AMD: sudo pacman -S mesa
# NVIDIA: sudo pacman -S libva-nvidia-driver
# Intel: sudo pacman -S libva-intel-driver intel-media-driverDebian/Ubuntu:
# GTK4 and WebKit fallback
sudo apt install libwebkitgtk-6.0-4 libgtk-4-1
# GStreamer for media playback
sudo apt install gstreamer1.0-tools gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-pipewire
# Hardware acceleration
sudo apt install gstreamer1.0-vaapi va-driver-allFull Changelog: v0.30.0...v0.31.0