Overview
Dumber uses three layout levels:
- Tabs group separate browser contexts.
- Workspaces hold a layout of panes.
- Panes display web pages and can be split, stacked, moved, resized, or closed.
Most browser-management actions are exposed through modal keybindings. Enter a mode, run one or more commands, then leave the mode. The default modes cover pane management, tabs, Vim-style scrolling, resizing, and session commands.
The browser chrome stays out of the way by default. Open the omnibox when you want to navigate; otherwise the pane is just the page or web app you are using. This makes Dumber work well as a side pane next to an editor, terminal, or another desktop application.
Features
Content-first browsing
- No permanent tab bar, bookmark bar, or toolbar around the page
- Omnibox and browser commands appear through keyboard shortcuts
- Web apps can feel closer to desktop applications because the browser frame is not always visible
- Works well as a narrow side pane next to an editor, terminal, or other application
Pane-based browsing
- Split panes horizontally or vertically
- Stack panes in the same area
- Move, resize, and close panes with modal keybindings
- Keep related pages together in a workspace
Keyboard workflow
- Pane, tab, Vim, resize, and session modes
- Vim/Zellij-style navigation patterns
- Search bangs such as
!g, !gi, and !ddg
- Launcher integration for
rofi, fuzzel, and dmenu
Desktop integration
- Wayland-native on Sway, Hyprland, River, Niri, and similar compositors
- Floating pane with configurable profile shortcuts
- Single
config.toml file with hot reload
Browser features
- Chromium Embedded Framework backend by default
- WebKit backend available as a fallback
- Built-in ad blocking based on uBlock filter lists (WebKit backend only; see Extensions and ad blocking)
- GPU-accelerated video through VA-API/VDPAU where supported
- Snapshot-based restoration of tabs, workspaces, and pane layout
Installation
Install script
curl -fsSL https://raw.githubusercontent.com/bnema/dumber/v0.32.0/install.sh | DUMBER_VERSION=v0.32.0 bash
dumber browse
Arch Linux
yay -S dumber-browser-bin # Pre-built binary
yay -S dumber-browser-git # Build from source
Flatpak
wget https://github.com/bnema/dumber/releases/latest/download/dumber.flatpak
flatpak install --user dumber.flatpak
flatpak run dev.bnema.Dumber browse
For dependencies, distribution notes, and troubleshooting, see the installation documentation.
Keyboard modes
Dumber uses modal keybindings for browser management. The default zellij keymap gives each mode its own key; set workspace.keymap = "tmux" to use a single prefix (Ctrl+Space) followed by one action key instead.
| Mode |
Default key |
Used for |
| Pane |
Ctrl+P |
Split, stack, close, and move panes |
| Tab |
Ctrl+T |
Create, close, switch, and rename tabs |
| Vim Mode |
Ctrl+Y |
Navigate the active webpage with configurable Vim-style sequences; arrow keys stay native and other app shortcuts wait until exit |
| Resize |
Ctrl+N |
Resize panes with hjkl or arrow keys |
| Session |
Ctrl+O |
Snapshot, restore, and browse sessions |
Floating pane
The floating pane is a temporary browser pane that can be toggled without changing the main workspace layout.
Alt+F toggles the floating pane and preserves its state while hidden.
Ctrl+W closes the active pane; if the floating pane is active, it is fully released for a fresh next open.
- Profile shortcuts such as
Alt+G are optional and configured under workspace.floating_pane.profiles.
- Some
Alt+<key> bindings may conflict with browser-engine shortcuts or desktop-level handlers.
See the floating pane reference for setup and behavior details.
Configuration
Dumber is configured with a single TOML file.
[engine]
type = "cef"
[workspace.floating_pane]
enabled = true
The config reloads while Dumber is running. See the configuration documentation for all options.
Extensions and ad blocking
CEF does not expose the Extensions API, so browser extensions are not supported. While WebKitGTK can use
injected filter lists, this approach is not available with CEF.
For consistent ad and tracker blocking across applications and devices, use network-level DNS filtering such as
AdGuard or Pi-hole. DNS filtering is more reliable than treating ad blocking as a browser extension, and it protects every device that uses your network.
Browser engine
Dumber uses Chromium Embedded Framework by default. WebKitGTK is available as a second option but I don't use it daily so it is more prone to bugs.
On Arch Linux, install the CEF runtime with:
sudo pacman -S cef libwebp
For hardware video decoding, cef-vaapi is also available from the AUR as an optional CEF build.
CEF runtime lookup order:
CEF_DIR
engine.cef.cef_dir
/usr/lib/cef
~/.local/share/cef
Set engine.cef.cef_dir in config when CEF_DIR is unset:
[engine.cef]
cef_dir = "/custom/path"
Or set the higher-precedence CEF_DIR environment variable:
CEF_DIR=/custom/path dumber browse
WebKit can be selected explicitly:
[engine]
type = "webkit"
Rendering
CEF uses Dumber's GPU-first Wayland render stack by default: GDK DMABUF presentation with ANGLE/GSK Vulkan. For driver compatibility, switch to the EGL/OpenGL stack with engine.cef.render_stack = "egl"; the default is "vulkan".
CEF OSR frame rate adapts to the active Wayland monitor refresh rate when both engine.cef.adaptive_windowless_frame_rate = true and engine.cef.windowless_frame_rate = 0 are set, which are the defaults. Adaptive mode is capped by engine.cef.windowless_frame_rate_max = 240. Setting engine.cef.windowless_frame_rate to a positive value forces a fixed rate instead. This adaptive polling path is Wayland-specific; other platforms fall back to the configured fixed/default CEF behavior.
Dependencies
Arch Linux:
sudo pacman -S cef webkitgtk-6.0 gtk4 libwebp gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugin-va
Debian/Ubuntu:
sudo apt install libwebkitgtk-6.0-4 libgtk-4-1 gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad
Ubuntu 24.04 ships GLib 2.80, but Dumber requires GLib 2.84+. Use Arch, Fedora 41+, or the Flatpak.
Development
Dumber uses pure-Go bindings. The GUI uses GTK4, runs on CEF by default, and can use WebKitGTK as a fallback backend.
Set ENV=dev to isolate the development process under .dev/dumber/. Dumber sets HOME plus XDG_CONFIG_HOME, XDG_DATA_HOME, XDG_STATE_HOME, and XDG_CACHE_HOME there before GTK or the browser engine starts, so development runs do not use production profiles, cookies, caches, or logs.
Build from source
Prerequisites:
- Go 1.27+
- GTK4 development packages
- CEF runtime (default backend)
- WebKitGTK 6.0 development/runtime packages (fallback backend and runtime checks)
- Brotli for compressed systemviews assets
- libwebp runtime for WebP favicon decoding (for example
libwebp on Arch)
Systemviews assets are generated with go tool templ and Go's js/wasm toolchain; no root Node toolchain is required.
git clone https://github.com/bnema/dumber
cd dumber
make build
./dist/dumber browse
Make targets
| Target |
Description |
make build |
Build systemviews assets and binary |
make build-quick |
Build binary only, skipping systemviews assets |
make check |
Run local all-clear checks for tools, build, generated assets, tests, and constraints |
make dev |
Run with go run |
make test |
Run tests |
make lint |
Run the pinned golangci-lint version |
make staticcheck |
Run Staticcheck with the pinned tool version |
make verify-generated |
Verify tracked generated systemviews artifacts are committed |
make flatpak-build |
Build Flatpak bundle |
Development tool versions are pinned in Makefile (GOLANGCI_LINT_VERSION, STATICCHECK_VERSION). Bump those values intentionally when refreshing lint/static analysis tooling.
Contributing
Dumber is currently focused on stability, performance, browser-engine behavior, and core UI/UX polish.
Bug fixes, documentation improvements, packaging fixes, and targeted UX improvements are welcome. Larger feature ideas should start as issues before PRs.
See CONTRIBUTING.md for details.
License
MIT - See LICENSE for details.
source
1<h1 align="center">Dumber</h1>
2
3<p align="center">
4 <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square" alt="License: MIT"></a>
5 <a href="https://github.com/bnema/dumber/releases"><img src="https://img.shields.io/badge/platform-Linux%20Wayland%20only-blue?style=flat-square" alt="Platform: Linux Wayland"></a>
6 <a href="https://github.com/bnema/dumber/commits/main"><img src="https://badgen.net/github/last-commit/bnema/dumber/main?icon=github" alt="Last commit"></a>
7 <a href="https://github.com/bnema/dumber/stargazers"><img src="https://badgen.net/github/stars/bnema/dumber?icon=github" alt="GitHub stars"></a>
8</p>
9
10<p align="center">Minimal Keyboard-driven web browser for tiling WMs, inspired by Zellij, built in Go.</p>
11
12<p align="center"><a href="https://bnema.dev/dumber">Website</a> · <a href="https://bnema.dev/dumber/docs">Documentation</a> · <a href="https://bnema.dev/dumber/docs/reference/keybindings">Keybindings</a></p>
13
14https://github.com/user-attachments/assets/232822af-08e4-4a74-9416-87f79c96b118
15
16## Overview
17
18Dumber uses three layout levels:
19
20- **Tabs** group separate browser contexts.
21- **Workspaces** hold a layout of panes.
22- **Panes** display web pages and can be split, stacked, moved, resized, or closed.
23
24Most browser-management actions are exposed through modal keybindings. Enter a mode, run one or more commands, then leave the mode. The default modes cover pane management, tabs, Vim-style scrolling, resizing, and session commands.
25
26The browser chrome stays out of the way by default. Open the omnibox when you want to navigate; otherwise the pane is just the page or web app you are using. This makes Dumber work well as a side pane next to an editor, terminal, or another desktop application.
27
28## Features
29
30### Content-first browsing
31
32- No permanent tab bar, bookmark bar, or toolbar around the page
33- Omnibox and browser commands appear through keyboard shortcuts
34- Web apps can feel closer to desktop applications because the browser frame is not always visible
35- Works well as a narrow side pane next to an editor, terminal, or other application
36
37### Pane-based browsing
38
39- Split panes horizontally or vertically
40- Stack panes in the same area
41- Move, resize, and close panes with modal keybindings
42- Keep related pages together in a workspace
43
44### Keyboard workflow
45
46- Pane, tab, Vim, resize, and session modes
47- Vim/Zellij-style navigation patterns
48- Search bangs such as `!g`, `!gi`, and `!ddg`
49- Launcher integration for `rofi`, `fuzzel`, and `dmenu`
50
51### Desktop integration
52
53- Wayland-native on Sway, Hyprland, River, Niri, and similar compositors
54- Floating pane with configurable profile shortcuts
55- Single `config.toml` file with hot reload
56
57### Browser features
58
59- Chromium Embedded Framework backend by default
60- WebKit backend available as a fallback
61- Built-in ad blocking based on uBlock filter lists (WebKit backend only; see [Extensions and ad blocking](#extensions-and-ad-blocking))
62- GPU-accelerated video through VA-API/VDPAU where supported
63- Snapshot-based restoration of tabs, workspaces, and pane layout
64
65## Installation
66
67### Install script
68
69```bash
70curl -fsSL https://raw.githubusercontent.com/bnema/dumber/v0.32.0/install.sh | DUMBER_VERSION=v0.32.0 bash
71dumber browse
72```
73
74### Arch Linux
75
76```bash
77yay -S dumber-browser-bin # Pre-built binary
78yay -S dumber-browser-git # Build from source
79```
80
81### Flatpak
82
83```bash
84wget https://github.com/bnema/dumber/releases/latest/download/dumber.flatpak
85flatpak install --user dumber.flatpak
86flatpak run dev.bnema.Dumber browse
87```
88
89For dependencies, distribution notes, and troubleshooting, see the [installation documentation](https://bnema.dev/dumber/docs).
90
91## Keyboard modes
92
93Dumber uses modal keybindings for browser management. The default `zellij` keymap gives each mode its own key; set `workspace.keymap = "tmux"` to use a single prefix (`Ctrl+Space`) followed by one action key instead.
94
95| Mode | Default key | Used for |
96|------|-------------|----------|
97| Pane | `Ctrl+P` | Split, stack, close, and move panes |
98| Tab | `Ctrl+T` | Create, close, switch, and rename tabs |
99| Vim Mode | `Ctrl+Y` | Navigate the active webpage with configurable Vim-style sequences; arrow keys stay native and other app shortcuts wait until exit |
100| Resize | `Ctrl+N` | Resize panes with `hjkl` or arrow keys |
101| Session | `Ctrl+O` | Snapshot, restore, and browse sessions |
102
103## Floating pane
104
105The floating pane is a temporary browser pane that can be toggled without changing the main workspace layout.
106
107- `Alt+F` toggles the floating pane and preserves its state while hidden.
108- `Ctrl+W` closes the active pane; if the floating pane is active, it is fully released for a fresh next open.
109- Profile shortcuts such as `Alt+G` are optional and configured under `workspace.floating_pane.profiles`.
110- Some `Alt+<key>` bindings may conflict with browser-engine shortcuts or desktop-level handlers.
111
112See the [floating pane reference](https://bnema.dev/dumber/docs/reference/floating-pane) for setup and behavior details.
113
114## Configuration
115
116Dumber is configured with a single TOML file.
117
118```toml
119[engine]
120type = "cef"
121
122[workspace.floating_pane]
123enabled = true
124```
125
126The config reloads while Dumber is running. See the [configuration documentation](https://bnema.dev/dumber/docs) for all options.
127
128## Extensions and ad blocking
129
130CEF does not expose the Extensions API, so browser extensions are not supported. While WebKitGTK can use
131injected filter lists, this approach is not available with CEF.
132
133For consistent ad and tracker blocking across applications and devices, use network-level DNS filtering such as
134[AdGuard](https://adguard.com/) or [Pi-hole](https://pi-hole.net/). DNS filtering is more reliable than treating ad blocking as a browser extension, and it protects every device that uses your network.
135
136## Browser engine
137
138Dumber uses Chromium Embedded Framework by default. WebKitGTK is available as a second option but I don't use it daily so it is more prone to bugs.
139
140On Arch Linux, install the CEF runtime with:
141
142```bash
143sudo pacman -S cef libwebp
144```
145
146For hardware video decoding, `cef-vaapi` is also available from the AUR as an optional CEF build.
147
148CEF runtime lookup order:
149
1501. `CEF_DIR`
1512. `engine.cef.cef_dir`
1523. `/usr/lib/cef`
1534. `~/.local/share/cef`
154
155Set `engine.cef.cef_dir` in config when `CEF_DIR` is unset:
156
157```toml
158[engine.cef]
159cef_dir = "/custom/path"
160```
161
162Or set the higher-precedence `CEF_DIR` environment variable:
163
164```bash
165CEF_DIR=/custom/path dumber browse
166```
167
168WebKit can be selected explicitly:
169
170```toml
171[engine]
172type = "webkit"
173```
174
175### Rendering
176
177CEF uses Dumber's GPU-first Wayland render stack by default: GDK DMABUF presentation with ANGLE/GSK Vulkan. For driver compatibility, switch to the EGL/OpenGL stack with `engine.cef.render_stack = "egl"`; the default is `"vulkan"`.
178
179CEF OSR frame rate adapts to the active Wayland monitor refresh rate when both `engine.cef.adaptive_windowless_frame_rate = true` and `engine.cef.windowless_frame_rate = 0` are set, which are the defaults. Adaptive mode is capped by `engine.cef.windowless_frame_rate_max = 240`. Setting `engine.cef.windowless_frame_rate` to a positive value forces a fixed rate instead. This adaptive polling path is Wayland-specific; other platforms fall back to the configured fixed/default CEF behavior.
180
181## Platform notes
182
183### Dependencies
184
185**Arch Linux:**
186
187```bash
188sudo pacman -S cef webkitgtk-6.0 gtk4 libwebp gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugin-va
189```
190
191**Debian/Ubuntu:**
192
193```bash
194sudo apt install libwebkitgtk-6.0-4 libgtk-4-1 gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad
195```
196
197> Ubuntu 24.04 ships GLib 2.80, but Dumber requires GLib 2.84+. Use Arch, Fedora 41+, or the Flatpak.
198
199## Development
200
201Dumber uses pure-Go bindings. The GUI uses GTK4, runs on CEF by default, and can use WebKitGTK as a fallback backend.
202
203Set `ENV=dev` to isolate the development process under `.dev/dumber/`. Dumber sets `HOME` plus `XDG_CONFIG_HOME`, `XDG_DATA_HOME`, `XDG_STATE_HOME`, and `XDG_CACHE_HOME` there before GTK or the browser engine starts, so development runs do not use production profiles, cookies, caches, or logs.
204
205### Build from source
206
207**Prerequisites:**
208
209- Go 1.27+
210- GTK4 development packages
211- CEF runtime (default backend)
212- WebKitGTK 6.0 development/runtime packages (fallback backend and runtime checks)
213- Brotli for compressed systemviews assets
214- libwebp runtime for WebP favicon decoding (for example `libwebp` on Arch)
215
216Systemviews assets are generated with `go tool templ` and Go's `js/wasm` toolchain; no root Node toolchain is required.
217
218```bash
219git clone https://github.com/bnema/dumber
220cd dumber
221make build
222./dist/dumber browse
223```
224
225### Make targets
226
227| Target | Description |
228|--------|-------------|
229| `make build` | Build systemviews assets and binary |
230| `make build-quick` | Build binary only, skipping systemviews assets |
231| `make check` | Run local all-clear checks for tools, build, generated assets, tests, and constraints |
232| `make dev` | Run with `go run` |
233| `make test` | Run tests |
234| `make lint` | Run the pinned golangci-lint version |
235| `make staticcheck` | Run Staticcheck with the pinned tool version |
236| `make verify-generated` | Verify tracked generated systemviews artifacts are committed |
237| `make flatpak-build` | Build Flatpak bundle |
238
239Development tool versions are pinned in `Makefile` (`GOLANGCI_LINT_VERSION`, `STATICCHECK_VERSION`). Bump those values intentionally when refreshing lint/static analysis tooling.
240
241## Contributing
242
243Dumber is currently focused on stability, performance, browser-engine behavior, and core UI/UX polish.
244
245Bug fixes, documentation improvements, packaging fixes, and targeted UX improvements are welcome. Larger feature ideas should start as issues before PRs.
246
247See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
248
249## Community
250
251- [Report bugs](https://github.com/bnema/dumber/issues)
252- [Releases](https://github.com/bnema/dumber/releases)
253
254## License
255
256MIT - See `LICENSE` for details.