v0.10.0 0f4e9eb

README.md RawHistoryFolder

Dumber, fully unfeatured unbloated browser for tiling WMs

Dumber is a minimalist browser and launcher companion focused on speed and simplicity. It ships a built‑in WebKitGTK (GTK4) window for navigation and a CLI with dmenu‑style launcher integration (rofi, fuzzel).

  • Native GUI via WebKitGTK 6 (GTK4, CGO) with an embedded homepage UI.
  • CLI that parses URLs, supports search shortcuts (e.g., g:query), and integrates with rofi/dmenu.
  • Persistent history and per‑domain zoom levels (SQLite, XDG locations).
  • Configurable via config.json and environment variables, with live reload.

Wayland‑First

  • Dumb on purpose, designed for Wayland window managers (Sway, Hyprland, River, Niri, etc..) it's a tiny companion that interact nicely with your launcher.
  • Uses a native Wayland WebKitGTK-6.0 window; no external browser required and no X11/XWayland dependency.
  • Optimized for dmenu‑style launchers (rofi, fuzzel, wofi) and keyboard‑driven workflows.

Status

  • Early development stage with regular releases. The workspace management system is fully functional and the browser works well for daily use. Expect some rough edges but core features are stable.

Features

  • Complete workspace management: Zellij-inspired pane splitting with binary tree layout, focus tracking, and modal keyboard controls
  • Multi-pane WebView architecture: Independent browsing sessions per pane with proper lifecycle management
  • Advanced popup handling: Intelligent popup management for tiling WMs - OAuth flows, window.open(), and popup deduplication
  • Window-level global shortcuts: Centralized shortcut handling to prevent conflicts between multiple WebView instances
  • GPU rendering and hardware video acceleration: Automatic GPU detection with VA-API/VDPAU support
  • Built-in ad blocker: UBlock-based content filtering (network blocking functional, cosmetic filtering in progress)
  • dmenu‑style launcher integration: rofi, fuzzel integration with history and shortcut suggestions
  • Comprehensive keyboard controls: Complete keyboard-driven workflow with shortcuts and gestures
  • Persistent history and zoom: SQLite-based history with per‑domain zoom persistence
  • Fully configurable: Single config file with live reload and environment variable overrides

Controls & Shortcuts

Keyboard Shortcuts

Browser Controls

Shortcut Action Notes
F12 Open Developer Tools WebKit inspector
Ctrl/Cmd+L Open Omnibox URL/search input with history
Ctrl/Cmd+F Find in Page Search text within current page
Ctrl/Cmd+= Zoom In Firefox-compatible zoom levels
Ctrl/Cmd++ Zoom In Alternative plus key
Ctrl/Cmd+- Zoom Out Works across keyboard layouts
Ctrl/Cmd+0 Reset Zoom Return to 100% zoom
Ctrl/Cmd+Shift+C Copy URL Copy current URL to clipboard with toast
Ctrl/Cmd+Shift+P Print Page Open native print dialog
Ctrl/Cmd+R / F5 Reload Page Refresh current page
Ctrl/Cmd+Shift+R Hard Reload Refresh ignoring cache
Ctrl+← / Ctrl+→ Navigate Back/Forward Browser history navigation

Zellij-Inspired Pane Management

Shortcut Action Notes
Ctrl/Cmd+P Enter Pane Mode Modal mode for pane operations
→ / R (in pane mode) Split Right Create new pane to the right
← / L (in pane mode) Split Left Create new pane to the left
↑ / U (in pane mode) Split Up Create new pane above
↓ / D (in pane mode) Split Down Create new pane below
X (in pane mode) Close Pane Close current pane
Enter (in pane mode) Confirm Action Confirm pane operation
Escape (in pane mode) Exit Pane Mode Return to normal navigation
Alt+Arrow Keys Navigate Panes Move focus between panes

Mouse Controls

Action Result Notes
Ctrl+Scroll Up Zoom In Smooth zoom control
Ctrl+Scroll Down Zoom Out Smooth zoom control
Mouse Button 8 Navigate Back Side button (back)
Mouse Button 9 Navigate Forward Side button (forward)
Two-finger Swipe Back/Forward When supported by touchpad

Omnibox/Find Mode (when active)

Shortcut Action Notes
Escape Close overlay Exit omnibox or find mode
Enter Execute/Navigate Navigate to URL or jump to match
Shift+Enter Previous Match Find mode: go to previous match
Alt+Enter Center Match Find mode: center on match, keep open
↑/↓ Arrow Navigate Results Browse suggestions/matches

All zoom changes are automatically persisted per-domain and restored on next visit.

Quick Start

Prerequisites:

  • Go 1.25+
  • Node.js 20+ and npm (for building the embedded TypeScript frontend)
  • For GUI build: WebKitGTK 6 and GTK4 dev packages (examples)
    • Debian/Ubuntu: libwebkitgtk-6.0-dev libgtk-4-dev build-essential
    • Arch: webkitgtk-6.0 gtk4 base-devel

Build options:

  • GUI (default, recommended):
    • make build # builds frontend + Go with -tags=webkit_cgo
    • Run: ./dist/dumber # opens the embedded homepage
  • CLI‑only (no GUI, CGO disabled):
    • make build-no-gui
    • Run: ./dist/dumber-no-gui version

Development:

  • make dev runs go run . (non‑CGO; GUI stubs log to console)
  • make test runs tests; make lint runs golangci‑lint

Install

Note: go install will not work for this project because the frontend assets must be built first and embedded into the binary. Use the build commands instead:

  • GUI build (default, recommended):
    • Ensure WebKit2GTK/GTK dev packages are installed (see prerequisites)
    • Clone the repo and run make build (builds frontend first, then Go with GUI support)
    • The resulting ./dist/dumber binary includes the native GUI window
  • CLI‑only (no native window):
    • Clone the repo and run make build-no-gui
    • The resulting ./dist/dumber-no-gui binary runs CLI flows with GUI code stubbed

Usage

  • Open a URL or search:
    • dumber browse https://example.com
    • dumber browse example.com # scheme auto‑added
    • dumber browse g:golang # Google search via shortcut
  • Launch the GUI directly:
    • dumber # no args → opens GUI homepage
  • Show version information:
    • dumber version # display version, commit, and build date
  • Launcher integration (dmenu‑style examples):
    • rofi: dumber dmenu | rofi -dmenu -p "Browse: " | dumber dmenu --select
    • fuzzel: dumber dmenu | fuzzel --dmenu -p "Browse: " | dumber dmenu --select
  • Manage browsing history:
    • dumber history # list recent history (default: 20 entries)
    • dumber history list -n 50 # list 50 recent entries
    • dumber history search golang # search history for "golang"
    • dumber history stats # show history statistics
    • dumber history clear # clear all history (with confirmation)
    • dumber history clear --force # clear all history (no confirmation)
  • Clean up data and cache:
    • dumber purge # purge all data (with confirmation)
    • dumber purge --force # purge all data (no confirmation)
    • dumber purge -d -H -c # purge database and both caches
    • dumber purge --browser-data # purge WebKit data (cookies, etc.)
  • Manage logs:
    • dumber logs list # list available log files
    • dumber logs tail # tail current log file
    • dumber logs clean # clean up old log files

Dmenu mode invocation

You can invoke dmenu mode in two ways:

  • Subcommand (recommended): dumber dmenu … and dumber dmenu --select
  • Root flag (generate options only): dumber --dmenu

Note: The root flag path only generates options; for processing a selection (--select), use the dmenu subcommand as the receiving command.

In GUI mode the app serves an embedded homepage via dumb://homepage, and frontend assets under dumb://app/....

Pane Management (Zellij-Inspired)

Dumber features a Zellij-inspired pane management system that allows you to split your browser window into multiple panes, each running independent web sessions.

How it Works

  1. Enter Pane Mode: Press Ctrl+P to enter pane mode (modal interface with timeout)
  2. Split Panes: Use arrow keys or letter shortcuts to split:
    • → or R - Split right
    • ← or L - Split left
    • ↑ or U - Split up
    • ↓ or D - Split down
  3. Navigate: Use Alt+Arrow Keys to move focus between panes
  4. Close: Press X in pane mode to close the current pane

Features

  • Binary tree layout: Panes are organized in a binary tree structure for optimal space usage
  • Focus management: Visual borders, hover-to-focus, and enhanced focus throttling (100ms) for intuitive navigation
  • Independent sessions: Each pane maintains its own browsing session, history, and zoom level
  • Advanced popup handling: Intelligent popup vs tab detection, OAuth auto-close, and popup deduplication with SHA256 fingerprinting
  • Cross-WebView communication: localStorage-based parent-popup bridge enabling proper window.opener functionality
  • WebView identity tracking: Unique WebView ID system for precise popup targeting and enhanced debugging
  • Keyboard-driven: All operations accessible via keyboard shortcuts with modal pane mode

Configuration

The pane system is fully configurable via config.json:

"workspace": {
  "enable_zellij_controls": true,
  "pane_mode": {
    "activation_shortcut": "cmdorctrl+p",
    "timeout_ms": 3000,
    "action_bindings": {
      "arrowright": "split-right",
      "r": "split-right",
      "x": "close-pane",
      // ... full key mappings
    }
  },
  "popups": {
    "placement": "right",
    "open_in_new_pane": true
  },
  "styling": {
    "border_width": 2,
    "border_color": "@theme_selected_bg_color",
    "transition_duration": 120
  }
}

Configuration

Dumber follows the XDG Base Directory spec:

  • Config: ~/.config/dumber/config.json
  • Data: ~/.local/share/dumber
  • State: ~/.local/state/dumber (default DB lives here)

A default config.json is created on first run. Config changes are watched and applied at runtime when possible.

Complete Configuration Reference

Database Configuration

"database": {
  "path": "~/.local/state/dumber/history.db",
  "max_connections": 1,
  "max_idle_time": "5m0s",
  "query_timeout": "30s"
}

History Management

"history": {
  "max_entries": 10000,
  "retention_period_days": 365,
  "cleanup_interval_days": 1
}

Search Shortcuts

"search_shortcuts": {
  "g":   { "url": "https://www.google.com/search?q=%s", "description": "Google search" },
  "gh":  { "url": "https://github.com/search?q=%s", "description": "GitHub search" },
  "yt":  { "url": "https://www.youtube.com/results?search_query=%s", "description": "YouTube search" },
  "w":   { "url": "https://en.wikipedia.org/wiki/%s", "description": "Wikipedia search" },
  "ddg": { "url": "https://duckduckgo.com/?q=%s", "description": "DuckDuckGo search" },
  "so":  { "url": "https://stackoverflow.com/search?q=%s", "description": "Stack Overflow search" },
  "r":   { "url": "https://www.reddit.com/search?q=%s", "description": "Reddit search" },
  "npm": { "url": "https://www.npmjs.com/search?q=%s", "description": "npm package search" },
  "go":  { "url": "https://pkg.go.dev/search?q=%s", "description": "Go package search" },
  "mdn": { "url": "https://developer.mozilla.org/en-US/search?q=%s", "description": "MDN Web Docs search" }
}

Dmenu Integration

"dmenu": {
  "max_history_items": 20,
  "show_visit_count": true,
  "show_last_visited": true,
  "history_prefix": "🕒",
  "shortcut_prefix": "🔍",
  "url_prefix": "🌐",
  "date_format": "2006-01-02 15:04",
  "sort_by_visit_count": true
}

Logging Configuration

"logging": {
  "level": "info",
  "format": "text",
  "filename": "",
  "max_size": 100,
  "max_backups": 3,
  "max_age": 7,
  "compress": true
}

Appearance Settings

"appearance": {
  "sans_font": "Fira Sans",
  "serif_font": "Fira Sans", 
  "monospace_font": "Fira Code",
  "default_font_size": 16
}

Rendering Mode (GPU/CPU)

"rendering_mode": "auto"
  • auto: Detect GPU availability and use GPU when available (default)
  • gpu: Force GPU acceleration (Vulkan/OpenGL via GTK4)
  • cpu: Force software rendering

Environment Variables

All config values can be overridden with environment variables using the DUMB_BROWSER_ prefix:

# Database
DUMB_BROWSER_DATABASE_PATH="./browser.db"
DUMB_BROWSER_DATABASE_MAX_CONNECTIONS=5

# Rendering mode (special variable name)
DUMBER_RENDERING_MODE="gpu"

# Dmenu settings
DUMB_BROWSER_DMENU_MAX_HISTORY_ITEMS=50
DUMB_BROWSER_DMENU_SHOW_VISIT_COUNT=false

# Logging
DUMB_BROWSER_LOGGING_LEVEL="debug"
DUMB_BROWSER_LOGGING_FORMAT="json"

CLI Flags

The browse command supports additional runtime flags:

dumber browse --rendering-mode=gpu https://example.com

Building With WebKitGTK 6 (GTK4)

  • The GUI requires building with -tags=webkit_cgo and CGO enabled.
  • Ensure WebKitGTK 6 and GTK4 dev headers are installed (see prerequisites).
  • Make targets handle both frontend and Go build steps:
    • make build-gui (CGO enabled)
    • make build (CGO enabled by default in the Makefile’s main build)

Without the native tag, a stub backend is used: you can still run CLI flows and see logs, but no native window is displayed.

Media (GStreamer) & Hardware Acceleration

WebKitGTK uses GStreamer for media playback. Dumber includes automatic hardware video acceleration support that detects your GPU and configures the appropriate drivers.

Hardware Acceleration Features:

  • Automatic GPU detection (AMD, NVIDIA, Intel)
  • VA-API and VDPAU driver configuration
  • Support for H.264, HEVC, VP9, and AV1 codecs
  • Significantly reduced CPU usage during video streaming

Required packages:

  • Arch Linux:
    • sudo pacman -S gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav gst-plugin-pipewire pipewire pipewire-pulse
    • Hardware accel: gstreamer-vaapi libva-mesa-driver (AMD), libva-vdpau-driver (NVIDIA), intel-media-driver (Intel)
  • Debian/Ubuntu:
    • 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 accel: gstreamer1.0-vaapi va-driver-all (covers most GPUs)

Theme and Runtime Updates

  • The homepage and pages respect your system’s light/dark preference.
  • The app updates color‑scheme live when your GTK theme changes (no relaunch needed).

Project Structure

  • main.go: Entry point with CLI/GUI routing
  • internal/app/cli: CLI application logic and Cobra commands
  • internal/app/browser: Browser application logic and WebKit integration
  • internal/cli: Cobra commands (browse, dmenu, version)
  • internal/config: Viper‑backed config, XDG helpers, defaults
  • internal/db: SQLite schema init and sqlc‑generated queries
  • internal/logging: Structured logging system with file rotation
  • services: Application services (parser/history/config/browser)
  • pkg/webkit: WebKit2GTK bindings (CGO and stub implementations)
  • pkg/clipboard: Cross-platform clipboard operations
  • frontend: TypeScript homepage UI bundled into the binary

Security & Privacy

  • History and zoom settings are stored locally in SQLite under XDG state.
  • The tmp/ directory is ignored by Git and kept out of history.

Roadmap

  • ✅ WebKitGTK 6 (GTK4) migration (GPU/Vulkan path complete)
  • ✅ GPU rendering (Vulkan via GTK4 renderer) with graceful CPU fallback
  • ✅ Zellij-inspired pane management with binary tree layout and keyboard-driven workflow
  • 🚧 UBlock-based content filtering (early stage - network blocking works, cosmetic filtering needs work)
  • Full Vim-style motion and keyboard navigation across pages and UI
  • Tab management system (browser tabs in addition to panes)
  • Performance work: faster startup, lower memory, snappier UI
  • Other shiny things I'm not yet aware of

License

This project is licensed under the MIT License. See LICENSE for details.

source
1# Dumber, fully unfeatured unbloated browser for tiling WMs
2
3<p align="center">
4  <img src="assets/logo.svg" alt="Dumber Logo" width="256" height="256" />
5</p>
6
7Dumber is a minimalist browser and launcher companion focused on speed and simplicity. It ships a built‑in WebKitGTK (GTK4) window for navigation and a CLI with dmenu‑style launcher integration (rofi, fuzzel).
8
9- Native GUI via WebKitGTK 6 (GTK4, CGO) with an embedded homepage UI.
10- CLI that parses URLs, supports search shortcuts (e.g., `g:query`), and integrates with rofi/dmenu.
11- Persistent history and per‑domain zoom levels (SQLite, XDG locations).
12- Configurable via `config.json` and environment variables, with live reload.
13
14## Wayland‑First
15- Dumb on purpose, designed for Wayland window managers (Sway, Hyprland, River, Niri, etc..) it's a tiny companion that interact nicely with your launcher.
16- Uses a native Wayland WebKitGTK-6.0 window; no external browser required and no X11/XWayland dependency.
17- Optimized for dmenu‑style launchers (rofi, fuzzel, wofi) and keyboard‑driven workflows.
18
19## Status
20- Early development stage with regular releases. The workspace management system is fully functional and the browser works well for daily use. Expect some rough edges but core features are stable.
21
22## Features
23- **Complete workspace management**: Zellij-inspired pane splitting with binary tree layout, focus tracking, and modal keyboard controls
24- **Multi-pane WebView architecture**: Independent browsing sessions per pane with proper lifecycle management
25- **Advanced popup handling**: Intelligent popup management for tiling WMs - OAuth flows, window.open(), and popup deduplication
26- **Window-level global shortcuts**: Centralized shortcut handling to prevent conflicts between multiple WebView instances
27- **GPU rendering and hardware video acceleration**: Automatic GPU detection with VA-API/VDPAU support
28- **Built-in ad blocker**: UBlock-based content filtering (network blocking functional, cosmetic filtering in progress)
29- **dmenu‑style launcher integration**: rofi, fuzzel integration with history and shortcut suggestions
30- **Comprehensive keyboard controls**: Complete keyboard-driven workflow with shortcuts and gestures
31- **Persistent history and zoom**: SQLite-based history with per‑domain zoom persistence
32- **Fully configurable**: Single config file with live reload and environment variable overrides
33
34## Controls & Shortcuts
35
36### Keyboard Shortcuts
37
38#### Browser Controls
39| Shortcut | Action | Notes |
40|----------|--------|-------|
41| **F12** | Open Developer Tools | WebKit inspector |
42| **Ctrl/Cmd+L** | Open Omnibox | URL/search input with history |
43| **Ctrl/Cmd+F** | Find in Page | Search text within current page |
44| **Ctrl/Cmd+=** | Zoom In | Firefox-compatible zoom levels |
45| **Ctrl/Cmd++** | Zoom In | Alternative plus key |
46| **Ctrl/Cmd+-** | Zoom Out | Works across keyboard layouts |
47| **Ctrl/Cmd+0** | Reset Zoom | Return to 100% zoom |
48| **Ctrl/Cmd+Shift+C** | Copy URL | Copy current URL to clipboard with toast |
49| **Ctrl/Cmd+Shift+P** | Print Page | Open native print dialog |
50| **Ctrl/Cmd+R** / **F5** | Reload Page | Refresh current page |
51| **Ctrl/Cmd+Shift+R** | Hard Reload | Refresh ignoring cache |
52| **Ctrl+←** / **Ctrl+→** | Navigate Back/Forward | Browser history navigation |
53
54#### Zellij-Inspired Pane Management
55| Shortcut | Action | Notes |
56|----------|--------|-------|
57| **Ctrl/Cmd+P** | Enter Pane Mode | Modal mode for pane operations |
58| **→** / **R** (in pane mode) | Split Right | Create new pane to the right |
59| **←** / **L** (in pane mode) | Split Left | Create new pane to the left |
60| **↑** / **U** (in pane mode) | Split Up | Create new pane above |
61| **↓** / **D** (in pane mode) | Split Down | Create new pane below |
62| **X** (in pane mode) | Close Pane | Close current pane |
63| **Enter** (in pane mode) | Confirm Action | Confirm pane operation |
64| **Escape** (in pane mode) | Exit Pane Mode | Return to normal navigation |
65| **Alt+Arrow Keys** | Navigate Panes | Move focus between panes |
66
67### Mouse Controls
68| Action | Result | Notes |
69|--------|---------|-------|
70| **Ctrl+Scroll Up** | Zoom In | Smooth zoom control |
71| **Ctrl+Scroll Down** | Zoom Out | Smooth zoom control |
72| **Mouse Button 8** | Navigate Back | Side button (back) |
73| **Mouse Button 9** | Navigate Forward | Side button (forward) |
74| **Two-finger Swipe** | Back/Forward | When supported by touchpad |
75
76### Omnibox/Find Mode (when active)
77| Shortcut | Action | Notes |
78|----------|--------|-------|
79| **Escape** | Close overlay | Exit omnibox or find mode |
80| **Enter** | Execute/Navigate | Navigate to URL or jump to match |
81| **Shift+Enter** | Previous Match | Find mode: go to previous match |
82| **Alt+Enter** | Center Match | Find mode: center on match, keep open |
83| **↑/↓ Arrow** | Navigate Results | Browse suggestions/matches |
84
85All zoom changes are automatically persisted per-domain and restored on next visit.
86
87## Quick Start
88Prerequisites:
89- Go 1.25+
90- Node.js 20+ and npm (for building the embedded TypeScript frontend)
91- For GUI build: WebKitGTK 6 and GTK4 dev packages (examples)
92  - Debian/Ubuntu: `libwebkitgtk-6.0-dev libgtk-4-dev build-essential`
93  - Arch: `webkitgtk-6.0 gtk4 base-devel`
94
95Build options:
96- GUI (default, recommended):
97  - `make build`          # builds frontend + Go with `-tags=webkit_cgo`
98  - Run: `./dist/dumber`  # opens the embedded homepage
99- CLI‑only (no GUI, CGO disabled):
100  - `make build-no-gui`
101  - Run: `./dist/dumber-no-gui version`
102
103Development:
104- `make dev` runs `go run .` (non‑CGO; GUI stubs log to console)
105- `make test` runs tests; `make lint` runs golangci‑lint
106
107## Install
108**Note**: `go install` will not work for this project because the frontend assets must be built first and embedded into the binary. Use the build commands instead:
109
110- GUI build (default, recommended):
111  - Ensure WebKit2GTK/GTK dev packages are installed (see prerequisites)
112  - Clone the repo and run `make build` (builds frontend first, then Go with GUI support)
113  - The resulting `./dist/dumber` binary includes the native GUI window
114- CLI‑only (no native window):
115  - Clone the repo and run `make build-no-gui`
116  - The resulting `./dist/dumber-no-gui` binary runs CLI flows with GUI code stubbed
117
118## Usage
119- Open a URL or search:
120  - `dumber browse https://example.com`
121  - `dumber browse example.com`        # scheme auto‑added
122  - `dumber browse g:golang`           # Google search via shortcut
123- Launch the GUI directly:
124  - `dumber`                           # no args → opens GUI homepage
125- Show version information:
126  - `dumber version`                   # display version, commit, and build date
127- Launcher integration (dmenu‑style examples):
128  - rofi:   `dumber dmenu | rofi -dmenu -p "Browse: " | dumber dmenu --select`
129  - fuzzel: `dumber dmenu | fuzzel --dmenu -p "Browse: " | dumber dmenu --select`
130- Manage browsing history:
131  - `dumber history`                   # list recent history (default: 20 entries)
132  - `dumber history list -n 50`       # list 50 recent entries
133  - `dumber history search golang`    # search history for "golang"
134  - `dumber history stats`            # show history statistics
135  - `dumber history clear`            # clear all history (with confirmation)
136  - `dumber history clear --force`    # clear all history (no confirmation)
137- Clean up data and cache:
138  - `dumber purge`                        # purge all data (with confirmation)
139  - `dumber purge --force`                # purge all data (no confirmation)
140  - `dumber purge -d -H -c`               # purge database and both caches
141  - `dumber purge --browser-data`         # purge WebKit data (cookies, etc.)
142- Manage logs:
143  - `dumber logs list`                    # list available log files
144  - `dumber logs tail`                    # tail current log file
145  - `dumber logs clean`                   # clean up old log files
146
147### Dmenu mode invocation
148You can invoke dmenu mode in two ways:
149- Subcommand (recommended): `dumber dmenu` … and `dumber dmenu --select`
150- Root flag (generate options only): `dumber --dmenu`
151
152Note: The root flag path only generates options; for processing a selection (`--select`), use the `dmenu` subcommand as the receiving command.
153
154In GUI mode the app serves an embedded homepage via `dumb://homepage`, and frontend assets under `dumb://app/...`.
155
156## Pane Management (Zellij-Inspired)
157
158Dumber features a Zellij-inspired pane management system that allows you to split your browser window into multiple panes, each running independent web sessions.
159
160### How it Works
1611. **Enter Pane Mode**: Press `Ctrl+P` to enter pane mode (modal interface with timeout)
1622. **Split Panes**: Use arrow keys or letter shortcuts to split:
163   - `→` or `R` - Split right
164   - `←` or `L` - Split left
165   - `↑` or `U` - Split up
166   - `↓` or `D` - Split down
1673. **Navigate**: Use `Alt+Arrow Keys` to move focus between panes
1684. **Close**: Press `X` in pane mode to close the current pane
169
170### Features
171- **Binary tree layout**: Panes are organized in a binary tree structure for optimal space usage
172- **Focus management**: Visual borders, hover-to-focus, and enhanced focus throttling (100ms) for intuitive navigation
173- **Independent sessions**: Each pane maintains its own browsing session, history, and zoom level
174- **Advanced popup handling**: Intelligent popup vs tab detection, OAuth auto-close, and popup deduplication with SHA256 fingerprinting
175- **Cross-WebView communication**: localStorage-based parent-popup bridge enabling proper `window.opener` functionality
176- **WebView identity tracking**: Unique WebView ID system for precise popup targeting and enhanced debugging
177- **Keyboard-driven**: All operations accessible via keyboard shortcuts with modal pane mode
178
179### Configuration
180The pane system is fully configurable via `config.json`:
181```json
182"workspace": {
183  "enable_zellij_controls": true,
184  "pane_mode": {
185    "activation_shortcut": "cmdorctrl+p",
186    "timeout_ms": 3000,
187    "action_bindings": {
188      "arrowright": "split-right",
189      "r": "split-right",
190      "x": "close-pane",
191      // ... full key mappings
192    }
193  },
194  "popups": {
195    "placement": "right",
196    "open_in_new_pane": true
197  },
198  "styling": {
199    "border_width": 2,
200    "border_color": "@theme_selected_bg_color",
201    "transition_duration": 120
202  }
203}
204```
205
206## Configuration
207
208Dumber follows the XDG Base Directory spec:
209- Config: `~/.config/dumber/config.json`
210- Data:   `~/.local/share/dumber`
211- State:  `~/.local/state/dumber` (default DB lives here)
212
213A default `config.json` is created on first run. Config changes are watched and applied at runtime when possible.
214
215### Complete Configuration Reference
216
217#### Database Configuration
218```json
219"database": {
220  "path": "~/.local/state/dumber/history.db",
221  "max_connections": 1,
222  "max_idle_time": "5m0s",
223  "query_timeout": "30s"
224}
225```
226
227#### History Management
228```json
229"history": {
230  "max_entries": 10000,
231  "retention_period_days": 365,
232  "cleanup_interval_days": 1
233}
234```
235
236#### Search Shortcuts
237```json
238"search_shortcuts": {
239  "g":   { "url": "https://www.google.com/search?q=%s", "description": "Google search" },
240  "gh":  { "url": "https://github.com/search?q=%s", "description": "GitHub search" },
241  "yt":  { "url": "https://www.youtube.com/results?search_query=%s", "description": "YouTube search" },
242  "w":   { "url": "https://en.wikipedia.org/wiki/%s", "description": "Wikipedia search" },
243  "ddg": { "url": "https://duckduckgo.com/?q=%s", "description": "DuckDuckGo search" },
244  "so":  { "url": "https://stackoverflow.com/search?q=%s", "description": "Stack Overflow search" },
245  "r":   { "url": "https://www.reddit.com/search?q=%s", "description": "Reddit search" },
246  "npm": { "url": "https://www.npmjs.com/search?q=%s", "description": "npm package search" },
247  "go":  { "url": "https://pkg.go.dev/search?q=%s", "description": "Go package search" },
248  "mdn": { "url": "https://developer.mozilla.org/en-US/search?q=%s", "description": "MDN Web Docs search" }
249}
250```
251
252#### Dmenu Integration
253```json
254"dmenu": {
255  "max_history_items": 20,
256  "show_visit_count": true,
257  "show_last_visited": true,
258  "history_prefix": "🕒",
259  "shortcut_prefix": "🔍",
260  "url_prefix": "🌐",
261  "date_format": "2006-01-02 15:04",
262  "sort_by_visit_count": true
263}
264```
265
266#### Logging Configuration
267```json
268"logging": {
269  "level": "info",
270  "format": "text",
271  "filename": "",
272  "max_size": 100,
273  "max_backups": 3,
274  "max_age": 7,
275  "compress": true
276}
277```
278
279#### Appearance Settings
280```json
281"appearance": {
282  "sans_font": "Fira Sans",
283  "serif_font": "Fira Sans", 
284  "monospace_font": "Fira Code",
285  "default_font_size": 16
286}
287```
288
289#### Rendering Mode (GPU/CPU)
290```json
291"rendering_mode": "auto"
292```
293- `auto`: Detect GPU availability and use GPU when available (default)
294- `gpu`: Force GPU acceleration (Vulkan/OpenGL via GTK4)
295- `cpu`: Force software rendering
296
297### Environment Variables
298All config values can be overridden with environment variables using the `DUMB_BROWSER_` prefix:
299
300```bash
301# Database
302DUMB_BROWSER_DATABASE_PATH="./browser.db"
303DUMB_BROWSER_DATABASE_MAX_CONNECTIONS=5
304
305# Rendering mode (special variable name)
306DUMBER_RENDERING_MODE="gpu"
307
308# Dmenu settings
309DUMB_BROWSER_DMENU_MAX_HISTORY_ITEMS=50
310DUMB_BROWSER_DMENU_SHOW_VISIT_COUNT=false
311
312# Logging
313DUMB_BROWSER_LOGGING_LEVEL="debug"
314DUMB_BROWSER_LOGGING_FORMAT="json"
315```
316
317### CLI Flags
318The browse command supports additional runtime flags:
319```bash
320dumber browse --rendering-mode=gpu https://example.com
321```
322
323
324## Building With WebKitGTK 6 (GTK4)
325- The GUI requires building with `-tags=webkit_cgo` and CGO enabled.
326- Ensure WebKitGTK 6 and GTK4 dev headers are installed (see prerequisites).
327- Make targets handle both frontend and Go build steps:
328  - `make build-gui` (CGO enabled)
329  - `make build` (CGO enabled by default in the Makefile’s main build)
330
331Without the native tag, a stub backend is used: you can still run CLI flows and see logs, but no native window is displayed.
332
333## Media (GStreamer) & Hardware Acceleration
334
335WebKitGTK uses GStreamer for media playback. Dumber includes automatic hardware video acceleration support that detects your GPU and configures the appropriate drivers.
336
337**Hardware Acceleration Features:**
338- Automatic GPU detection (AMD, NVIDIA, Intel)
339- VA-API and VDPAU driver configuration
340- Support for H.264, HEVC, VP9, and AV1 codecs
341- Significantly reduced CPU usage during video streaming
342
343**Required packages:**
344- Arch Linux:
345  - `sudo pacman -S gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav gst-plugin-pipewire pipewire pipewire-pulse`
346  - Hardware accel: `gstreamer-vaapi libva-mesa-driver` (AMD), `libva-vdpau-driver` (NVIDIA), `intel-media-driver` (Intel)
347- Debian/Ubuntu:
348  - `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`
349  - Hardware accel: `gstreamer1.0-vaapi va-driver-all` (covers most GPUs)
350
351## Theme and Runtime Updates
352- The homepage and pages respect your system’s light/dark preference.
353- The app updates color‑scheme live when your GTK theme changes (no relaunch needed).
354
355## Project Structure
356- `main.go`: Entry point with CLI/GUI routing
357- `internal/app/cli`: CLI application logic and Cobra commands
358- `internal/app/browser`: Browser application logic and WebKit integration
359- `internal/cli`: Cobra commands (`browse`, `dmenu`, `version`)
360- `internal/config`: Viper‑backed config, XDG helpers, defaults
361- `internal/db`: SQLite schema init and sqlc‑generated queries
362- `internal/logging`: Structured logging system with file rotation
363- `services`: Application services (parser/history/config/browser)
364- `pkg/webkit`: WebKit2GTK bindings (CGO and stub implementations)
365- `pkg/clipboard`: Cross-platform clipboard operations
366- `frontend`: TypeScript homepage UI bundled into the binary
367
368## Security & Privacy
369- History and zoom settings are stored locally in SQLite under XDG state.
370- The `tmp/` directory is ignored by Git and kept out of history.
371
372## Roadmap
373- ✅ WebKitGTK 6 (GTK4) migration (GPU/Vulkan path complete)
374- ✅ GPU rendering (Vulkan via GTK4 renderer) with graceful CPU fallback
375- ✅ Zellij-inspired pane management with binary tree layout and keyboard-driven workflow
376- 🚧 UBlock-based content filtering (early stage - network blocking works, cosmetic filtering needs work)
377- Full Vim-style motion and keyboard navigation across pages and UI
378- Tab management system (browser tabs in addition to panes)
379- Performance work: faster startup, lower memory, snappier UI
380- Other shiny things I'm not yet aware of
381
382## License
383This project is licensed under the MIT License. See `LICENSE` for details.

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close