docs: update keyboard shortcuts and config documentation
Updates README with Ctrl+ only shortcuts (removes Cmd/Ctrl variants), simplifies config reference to point to docs/CONFIG.md, adds JSON Schema feature to CHANGELOG, and notes BREAKING change for keyboard shortcuts migration.
- commit
- 2e8f954aa38e2830980fe922a5cb5d3ac3fad2dd
- author
- bnema · · 2025-10-23 20:48 UTC
- committer
- bnema · · 2025-10-24 17:33 UTC
- parent
- a5becb3
- signature
- GPG Unverified
2B82207D370127A0The key is unknown
3 files · +330 -129
M CHANGELOG.md +3 -1
| @@ -9,14 +9,16 @@ All notable changes to this project will be documented in this file. | |||
| 9 | 9 | - **DNS prefetch**: Added capability to prefetch DNS for links to speed up future requests | |
| 10 | 10 | - **Page cache (bfcache)**: Enabled WebKit back/forward cache for instant navigation | |
| 11 | 11 | - **Smooth scrolling**: Enabled WebKit smooth scrolling for better UX | |
| 12 | + | - **JSON Schema**: Auto-generated config schema for IDE autocompletion and validation | |
| 12 | 13 | ||
| 13 | 14 | ### Changed | |
| 14 | 15 | - **Database performance**: Enabled WAL mode with optimized PRAGMAs (64MB cache, memory-mapped I/O, 5s busy timeout) for 70k reads/sec, 3.6k writes/sec | |
| 15 | 16 | - **Zoom performance**: In-memory cache eliminates database reads during page transitions | |
| 16 | 17 | - **History writes**: Batched writes with background processor (flush every 5s or 50 items) to reduce I/O overhead | |
| 18 | + | - **BREAKING: Keyboard shortcuts**: All shortcuts now use `ctrl+` instead of `cmdorctrl+`. Existing configs with `cmdorctrl` still work via backward compatibility. Delete `~/.config/dumber/config.json` to regenerate with new defaults. | |
| 17 | 19 | ||
| 18 | 20 | ### Fixed | |
| 19 | - | - **Graceful shutdown deadlock**: Resolved GTK main loop deadlock on Cmd+Q by removing mutex locks and GTK calls after main loop exit | |
| 21 | + | - **Graceful shutdown deadlock**: Resolved GTK main loop deadlock on Ctrl+Q by removing mutex locks and GTK calls after main loop exit | |
| 20 | 22 | - Command typos now show proper error instead of opening in browser | |
| 21 | 23 | - History queue now uses buffered channel to prevent blocking on shutdown | |
| 22 | 24 | ||
| @@ -9,14 +9,16 @@ All notable changes to this project will be documented in this file. | |||||
| 9 | - **DNS prefetch**: Added capability to prefetch DNS for links to speed up future requests | 9 | - **DNS prefetch**: Added capability to prefetch DNS for links to speed up future requests | ||
| 10 | - **Page cache (bfcache)**: Enabled WebKit back/forward cache for instant navigation | 10 | - **Page cache (bfcache)**: Enabled WebKit back/forward cache for instant navigation | ||
| 11 | - **Smooth scrolling**: Enabled WebKit smooth scrolling for better UX | 11 | - **Smooth scrolling**: Enabled WebKit smooth scrolling for better UX | ||
| 12 | + | - **JSON Schema**: Auto-generated config schema for IDE autocompletion and validation | |||
| 12 | 13 | ||||
| 13 | ### Changed | 14 | ### Changed | ||
| 14 | - **Database performance**: Enabled WAL mode with optimized PRAGMAs (64MB cache, memory-mapped I/O, 5s busy timeout) for 70k reads/sec, 3.6k writes/sec | 15 | - **Database performance**: Enabled WAL mode with optimized PRAGMAs (64MB cache, memory-mapped I/O, 5s busy timeout) for 70k reads/sec, 3.6k writes/sec | ||
| 15 | - **Zoom performance**: In-memory cache eliminates database reads during page transitions | 16 | - **Zoom performance**: In-memory cache eliminates database reads during page transitions | ||
| 16 | - **History writes**: Batched writes with background processor (flush every 5s or 50 items) to reduce I/O overhead | 17 | - **History writes**: Batched writes with background processor (flush every 5s or 50 items) to reduce I/O overhead | ||
| 18 | + | - **BREAKING: Keyboard shortcuts**: All shortcuts now use `ctrl+` instead of `cmdorctrl+`. Existing configs with `cmdorctrl` still work via backward compatibility. Delete `~/.config/dumber/config.json` to regenerate with new defaults. | |||
| 17 | 19 | ||||
| 18 | ### Fixed | 20 | ### Fixed | ||
| 19 | - | - **Graceful shutdown deadlock**: Resolved GTK main loop deadlock on Cmd+Q by removing mutex locks and GTK calls after main loop exit | 21 | + | - **Graceful shutdown deadlock**: Resolved GTK main loop deadlock on Ctrl+Q by removing mutex locks and GTK calls after main loop exit |
| 20 | - Command typos now show proper error instead of opening in browser | 22 | - Command typos now show proper error instead of opening in browser | ||
| 21 | - History queue now uses buffered channel to prevent blocking on shutdown | 23 | - History queue now uses buffered channel to prevent blocking on shutdown | ||
| 22 | 24 | ||||
M README.md +32 -128
| @@ -41,22 +41,22 @@ Dumber is a minimalist browser and launcher companion focused on speed and simpl | |||
| 41 | 41 | | Shortcut | Action | Notes | | |
| 42 | 42 | |----------|--------|-------| | |
| 43 | 43 | | **F12** | Open Developer Tools | WebKit inspector | | |
| 44 | - | | **Ctrl/Cmd+L** | Open Omnibox | URL/search input with history | | |
| 45 | - | | **Ctrl/Cmd+F** | Find in Page | Search text within current page | | |
| 46 | - | | **Ctrl/Cmd+=** | Zoom In | Firefox-compatible zoom levels | | |
| 47 | - | | **Ctrl/Cmd++** | Zoom In | Alternative plus key | | |
| 48 | - | | **Ctrl/Cmd+-** | Zoom Out | Works across keyboard layouts | | |
| 49 | - | | **Ctrl/Cmd+0** | Reset Zoom | Return to 100% zoom | | |
| 50 | - | | **Ctrl/Cmd+Shift+C** | Copy URL | Copy current URL to clipboard with toast | | |
| 51 | - | | **Ctrl/Cmd+Shift+P** | Print Page | Open native print dialog | | |
| 52 | - | | **Ctrl/Cmd+R** / **F5** | Reload Page | Refresh current page | | |
| 53 | - | | **Ctrl/Cmd+Shift+R** | Hard Reload | Refresh ignoring cache | | |
| 44 | + | | **Ctrl+L** | Open Omnibox | URL/search input with history | | |
| 45 | + | | **Ctrl+F** | Find in Page | Search text within current page | | |
| 46 | + | | **Ctrl+=** | Zoom In | Firefox-compatible zoom levels | | |
| 47 | + | | **Ctrl++** | Zoom In | Alternative plus key | | |
| 48 | + | | **Ctrl+-** | Zoom Out | Works across keyboard layouts | | |
| 49 | + | | **Ctrl+0** | Reset Zoom | Return to 100% zoom | | |
| 50 | + | | **Ctrl+Shift+C** | Copy URL | Copy current URL to clipboard with toast | | |
| 51 | + | | **Ctrl+Shift+P** | Print Page | Open native print dialog | | |
| 52 | + | | **Ctrl+R** / **F5** | Reload Page | Refresh current page | | |
| 53 | + | | **Ctrl+Shift+R** | Hard Reload | Refresh ignoring cache | | |
| 54 | 54 | | **Ctrl+←** / **Ctrl+→** | Navigate Back/Forward | Browser history navigation | | |
| 55 | 55 | ||
| 56 | 56 | #### Zellij-Inspired Pane Management | |
| 57 | 57 | | Shortcut | Action | Notes | | |
| 58 | 58 | |----------|--------|-------| | |
| 59 | - | | **Ctrl/Cmd+P** | Enter Pane Mode | Modal mode for pane operations | | |
| 59 | + | | **Ctrl+P** | Enter Pane Mode | Modal mode for pane operations | | |
| 60 | 60 | | **→** / **R** (in pane mode) | Split Right | Create new pane to the right | | |
| 61 | 61 | | **←** / **L** (in pane mode) | Split Left | Create new pane to the left | | |
| 62 | 62 | | **↑** / **U** (in pane mode) | Split Up | Create new pane above | | |
| @@ -178,7 +178,7 @@ The pane system is fully configurable via `config.json`: | |||
| 178 | 178 | "workspace": { | |
| 179 | 179 | "enable_zellij_controls": true, | |
| 180 | 180 | "pane_mode": { | |
| 181 | - | "activation_shortcut": "cmdorctrl+p", | |
| 181 | + | "activation_shortcut": "ctrl+p", | |
| 182 | 182 | "timeout_ms": 3000, | |
| 183 | 183 | "action_bindings": { | |
| 184 | 184 | "arrowright": "split-right", | |
| @@ -208,134 +208,38 @@ Dumber follows the XDG Base Directory spec: | |||
| 208 | 208 | ||
| 209 | 209 | A default `config.json` is created on first run. Config changes are watched and applied at runtime when possible. | |
| 210 | 210 | ||
| 211 | - | ### Complete Configuration Reference | |
| 211 | + | ### How Configuration Works | |
| 212 | 212 | ||
| 213 | - | #### Database Configuration | |
| 214 | - | ```json | |
| 215 | - | "database": { | |
| 216 | - | "path": "~/.local/state/dumber/history.db", | |
| 217 | - | "max_connections": 1, | |
| 218 | - | "max_idle_time": "5m0s", | |
| 219 | - | "query_timeout": "30s" | |
| 220 | - | } | |
| 221 | - | ``` | |
| 213 | + | - **Config file**: `~/.config/dumber/config.json` (supports `.yaml` and `.toml` too) | |
| 214 | + | - **Format**: JSON/YAML/TOML - auto-detected | |
| 215 | + | - **JSON Schema**: Auto-generated for IDE autocompletion and validation | |
| 216 | + | - **Live reload**: Changes are automatically applied without restarting | |
| 217 | + | - **Environment variables**: Override any setting with `DUMB_BROWSER_*` or `DUMBER_*` prefix | |
| 218 | + | - **Default values**: Sensible defaults for all settings | |
| 222 | 219 | ||
| 223 | - | #### History Management | |
| 224 | - | ```json | |
| 225 | - | "history": { | |
| 226 | - | "max_entries": 10000, | |
| 227 | - | "retention_period_days": 365, | |
| 228 | - | "cleanup_interval_days": 1 | |
| 229 | - | } | |
| 230 | - | ``` | |
| 220 | + | ### Quick Examples | |
| 231 | 221 | ||
| 232 | - | #### Search Shortcuts | |
| 233 | 222 | ```json | |
| 234 | - | "search_shortcuts": { | |
| 235 | - | "g": { "url": "https://www.google.com/search?q=%s", "description": "Google search" }, | |
| 236 | - | "gh": { "url": "https://github.com/search?q=%s", "description": "GitHub search" }, | |
| 237 | - | "yt": { "url": "https://www.youtube.com/results?search_query=%s", "description": "YouTube search" }, | |
| 238 | - | "w": { "url": "https://en.wikipedia.org/wiki/%s", "description": "Wikipedia search" }, | |
| 239 | - | "ddg": { "url": "https://duckduckgo.com/?q=%s", "description": "DuckDuckGo search" }, | |
| 240 | - | "so": { "url": "https://stackoverflow.com/search?q=%s", "description": "Stack Overflow search" }, | |
| 241 | - | "r": { "url": "https://www.reddit.com/search?q=%s", "description": "Reddit search" }, | |
| 242 | - | "npm": { "url": "https://www.npmjs.com/search?q=%s", "description": "npm package search" }, | |
| 243 | - | "go": { "url": "https://pkg.go.dev/search?q=%s", "description": "Go package search" }, | |
| 244 | - | "mdn": { "url": "https://developer.mozilla.org/en-US/search?q=%s", "description": "MDN Web Docs search" } | |
| 245 | - | } | |
| 246 | - | ``` | |
| 247 | - | ||
| 248 | - | #### Dmenu Integration | |
| 249 | - | ```json | |
| 250 | - | "dmenu": { | |
| 251 | - | "max_history_items": 20, | |
| 252 | - | "show_visit_count": true, | |
| 253 | - | "show_last_visited": true, | |
| 254 | - | "history_prefix": "🕒", | |
| 255 | - | "shortcut_prefix": "🔍", | |
| 256 | - | "url_prefix": "🌐", | |
| 257 | - | "date_format": "2006-01-02 15:04", | |
| 258 | - | "sort_by_visit_count": true | |
| 259 | - | } | |
| 260 | - | ``` | |
| 261 | - | ||
| 262 | - | #### Logging Configuration | |
| 263 | - | ```json | |
| 264 | - | "logging": { | |
| 265 | - | "level": "info", | |
| 266 | - | "format": "text", | |
| 267 | - | "filename": "", | |
| 268 | - | "max_size": 100, | |
| 269 | - | "max_backups": 3, | |
| 270 | - | "max_age": 7, | |
| 271 | - | "compress": true | |
| 272 | - | } | |
| 273 | - | ``` | |
| 274 | - | ||
| 275 | - | #### Appearance Settings | |
| 276 | - | ```json | |
| 277 | - | "appearance": { | |
| 278 | - | "color_scheme": "default", | |
| 279 | - | "sans_font": "Fira Sans", | |
| 280 | - | "serif_font": "Fira Sans", | |
| 281 | - | "monospace_font": "Fira Code", | |
| 282 | - | "default_font_size": 16, | |
| 223 | + | { | |
| 283 | 224 | "default_zoom": 1.2, | |
| 284 | - | "color_palette": { | |
| 285 | - | "light": { | |
| 286 | - | "background": "#ffffff", | |
| 287 | - | "surface": "#f5f5f5", | |
| 288 | - | "text": "#1a1a1a", | |
| 289 | - | "text_muted": "#6b7280", | |
| 290 | - | "accent": "#3b82f6", | |
| 291 | - | "border": "#e5e7eb" | |
| 292 | - | }, | |
| 293 | - | "dark": { | |
| 294 | - | "background": "#0a0a0a", | |
| 295 | - | "surface": "#1a1a1a", | |
| 296 | - | "text": "#e5e7eb", | |
| 297 | - | "text_muted": "#9ca3af", | |
| 298 | - | "accent": "#60a5fa", | |
| 299 | - | "border": "#374151" | |
| 300 | - | } | |
| 225 | + | "rendering_mode": "gpu", | |
| 226 | + | "search_shortcuts": { | |
| 227 | + | "g": { "url": "https://google.com/search?q=%s", "description": "Google" } | |
| 228 | + | }, | |
| 229 | + | "workspace": { | |
| 230 | + | "enable_zellij_controls": true, | |
| 231 | + | "popups": { "behavior": "split" } | |
| 301 | 232 | } | |
| 302 | 233 | } | |
| 303 | 234 | ``` | |
| 304 | - | - `color_scheme`: `"prefer-dark"`, `"prefer-light"`, or `"default"` (follows system theme) | |
| 305 | - | ||
| 306 | - | #### Rendering Mode (GPU/CPU) | |
| 307 | - | ```json | |
| 308 | - | "rendering_mode": "auto" | |
| 309 | - | ``` | |
| 310 | - | - `auto`: Detect GPU availability and use GPU when available (default) | |
| 311 | - | - `gpu`: Force GPU acceleration (Vulkan/OpenGL via GTK4) | |
| 312 | - | - `cpu`: Force software rendering | |
| 313 | - | ||
| 314 | - | ### Environment Variables | |
| 315 | - | All config values can be overridden with environment variables using the `DUMB_BROWSER_` prefix: | |
| 316 | 235 | ||
| 236 | + | Environment variable override: | |
| 317 | 237 | ```bash | |
| 318 | - | # Database | |
| 319 | - | DUMB_BROWSER_DATABASE_PATH="./browser.db" | |
| 320 | - | DUMB_BROWSER_DATABASE_MAX_CONNECTIONS=5 | |
| 321 | - | ||
| 322 | - | # Rendering mode (special variable name) | |
| 323 | - | DUMBER_RENDERING_MODE="gpu" | |
| 324 | - | ||
| 325 | - | # Dmenu settings | |
| 326 | - | DUMB_BROWSER_DMENU_MAX_HISTORY_ITEMS=50 | |
| 327 | - | DUMB_BROWSER_DMENU_SHOW_VISIT_COUNT=false | |
| 328 | - | ||
| 329 | - | # Logging | |
| 330 | - | DUMB_BROWSER_LOGGING_LEVEL="debug" | |
| 331 | - | DUMB_BROWSER_LOGGING_FORMAT="json" | |
| 238 | + | DUMBER_RENDERING_MODE=cpu dumber | |
| 239 | + | DUMB_BROWSER_LOGGING_LEVEL=debug dumber | |
| 332 | 240 | ``` | |
| 333 | 241 | ||
| 334 | - | ### CLI Flags | |
| 335 | - | The browse command supports additional runtime flags: | |
| 336 | - | ```bash | |
| 337 | - | dumber browse --rendering-mode=gpu https://example.com | |
| 338 | - | ``` | |
| 242 | + | **📖 Complete documentation**: See [docs/CONFIG.md](docs/CONFIG.md) for all available settings, defaults, and valid values. | |
| 339 | 243 | ||
| 340 | 244 | ||
| 341 | 245 | ## Building With WebKitGTK 6 (GTK4) | |
| @@ -41,22 +41,22 @@ Dumber is a minimalist browser and launcher companion focused on speed and simpl | |||||
| 41 | | Shortcut | Action | Notes | | 41 | | Shortcut | Action | Notes | | ||
| 42 | |----------|--------|-------| | 42 | |----------|--------|-------| | ||
| 43 | | **F12** | Open Developer Tools | WebKit inspector | | 43 | | **F12** | Open Developer Tools | WebKit inspector | | ||
| 44 | - | | **Ctrl/Cmd+L** | Open Omnibox | URL/search input with history | | 44 | + | | **Ctrl+L** | Open Omnibox | URL/search input with history | |
| 45 | - | | **Ctrl/Cmd+F** | Find in Page | Search text within current page | | 45 | + | | **Ctrl+F** | Find in Page | Search text within current page | |
| 46 | - | | **Ctrl/Cmd+=** | Zoom In | Firefox-compatible zoom levels | | 46 | + | | **Ctrl+=** | Zoom In | Firefox-compatible zoom levels | |
| 47 | - | | **Ctrl/Cmd++** | Zoom In | Alternative plus key | | 47 | + | | **Ctrl++** | Zoom In | Alternative plus key | |
| 48 | - | | **Ctrl/Cmd+-** | Zoom Out | Works across keyboard layouts | | 48 | + | | **Ctrl+-** | Zoom Out | Works across keyboard layouts | |
| 49 | - | | **Ctrl/Cmd+0** | Reset Zoom | Return to 100% zoom | | 49 | + | | **Ctrl+0** | Reset Zoom | Return to 100% zoom | |
| 50 | - | | **Ctrl/Cmd+Shift+C** | Copy URL | Copy current URL to clipboard with toast | | 50 | + | | **Ctrl+Shift+C** | Copy URL | Copy current URL to clipboard with toast | |
| 51 | - | | **Ctrl/Cmd+Shift+P** | Print Page | Open native print dialog | | 51 | + | | **Ctrl+Shift+P** | Print Page | Open native print dialog | |
| 52 | - | | **Ctrl/Cmd+R** / **F5** | Reload Page | Refresh current page | | 52 | + | | **Ctrl+R** / **F5** | Reload Page | Refresh current page | |
| 53 | - | | **Ctrl/Cmd+Shift+R** | Hard Reload | Refresh ignoring cache | | 53 | + | | **Ctrl+Shift+R** | Hard Reload | Refresh ignoring cache | |
| 54 | | **Ctrl+←** / **Ctrl+→** | Navigate Back/Forward | Browser history navigation | | 54 | | **Ctrl+←** / **Ctrl+→** | Navigate Back/Forward | Browser history navigation | | ||
| 55 | 55 | ||||
| 56 | #### Zellij-Inspired Pane Management | 56 | #### Zellij-Inspired Pane Management | ||
| 57 | | Shortcut | Action | Notes | | 57 | | Shortcut | Action | Notes | | ||
| 58 | |----------|--------|-------| | 58 | |----------|--------|-------| | ||
| 59 | - | | **Ctrl/Cmd+P** | Enter Pane Mode | Modal mode for pane operations | | 59 | + | | **Ctrl+P** | Enter Pane Mode | Modal mode for pane operations | |
| 60 | | **→** / **R** (in pane mode) | Split Right | Create new pane to the right | | 60 | | **→** / **R** (in pane mode) | Split Right | Create new pane to the right | | ||
| 61 | | **←** / **L** (in pane mode) | Split Left | Create new pane to the left | | 61 | | **←** / **L** (in pane mode) | Split Left | Create new pane to the left | | ||
| 62 | | **↑** / **U** (in pane mode) | Split Up | Create new pane above | | 62 | | **↑** / **U** (in pane mode) | Split Up | Create new pane above | | ||
| @@ -178,7 +178,7 @@ The pane system is fully configurable via `config.json`: | |||||
| 178 | "workspace": { | 178 | "workspace": { | ||
| 179 | "enable_zellij_controls": true, | 179 | "enable_zellij_controls": true, | ||
| 180 | "pane_mode": { | 180 | "pane_mode": { | ||
| 181 | - | "activation_shortcut": "cmdorctrl+p", | 181 | + | "activation_shortcut": "ctrl+p", |
| 182 | "timeout_ms": 3000, | 182 | "timeout_ms": 3000, | ||
| 183 | "action_bindings": { | 183 | "action_bindings": { | ||
| 184 | "arrowright": "split-right", | 184 | "arrowright": "split-right", | ||
| @@ -208,134 +208,38 @@ Dumber follows the XDG Base Directory spec: | |||||
| 208 | 208 | ||||
| 209 | A default `config.json` is created on first run. Config changes are watched and applied at runtime when possible. | 209 | A default `config.json` is created on first run. Config changes are watched and applied at runtime when possible. | ||
| 210 | 210 | ||||
| 211 | - | ### Complete Configuration Reference | 211 | + | ### How Configuration Works |
| 212 | 212 | ||||
| 213 | - | #### Database Configuration | 213 | + | - **Config file**: `~/.config/dumber/config.json` (supports `.yaml` and `.toml` too) |
| 214 | - | ```json | 214 | + | - **Format**: JSON/YAML/TOML - auto-detected |
| 215 | - | "database": { | 215 | + | - **JSON Schema**: Auto-generated for IDE autocompletion and validation |
| 216 | - | "path": "~/.local/state/dumber/history.db", | 216 | + | - **Live reload**: Changes are automatically applied without restarting |
| 217 | - | "max_connections": 1, | 217 | + | - **Environment variables**: Override any setting with `DUMB_BROWSER_*` or `DUMBER_*` prefix |
| 218 | - | "max_idle_time": "5m0s", | 218 | + | - **Default values**: Sensible defaults for all settings |
| 219 | - | "query_timeout": "30s" | |||
| 220 | - | } | |||
| 221 | - | ``` | |||
| 222 | 219 | ||||
| 223 | - | #### History Management | 220 | + | ### Quick Examples |
| 224 | - | ```json | |||
| 225 | - | "history": { | |||
| 226 | - | "max_entries": 10000, | |||
| 227 | - | "retention_period_days": 365, | |||
| 228 | - | "cleanup_interval_days": 1 | |||
| 229 | - | } | |||
| 230 | - | ``` | |||
| 231 | 221 | ||||
| 232 | - | #### Search Shortcuts | |||
| 233 | ```json | 222 | ```json | ||
| 234 | - | "search_shortcuts": { | 223 | + | { |
| 235 | - | "g": { "url": "https://www.google.com/search?q=%s", "description": "Google search" }, | |||
| 236 | - | "gh": { "url": "https://github.com/search?q=%s", "description": "GitHub search" }, | |||
| 237 | - | "yt": { "url": "https://www.youtube.com/results?search_query=%s", "description": "YouTube search" }, | |||
| 238 | - | "w": { "url": "https://en.wikipedia.org/wiki/%s", "description": "Wikipedia search" }, | |||
| 239 | - | "ddg": { "url": "https://duckduckgo.com/?q=%s", "description": "DuckDuckGo search" }, | |||
| 240 | - | "so": { "url": "https://stackoverflow.com/search?q=%s", "description": "Stack Overflow search" }, | |||
| 241 | - | "r": { "url": "https://www.reddit.com/search?q=%s", "description": "Reddit search" }, | |||
| 242 | - | "npm": { "url": "https://www.npmjs.com/search?q=%s", "description": "npm package search" }, | |||
| 243 | - | "go": { "url": "https://pkg.go.dev/search?q=%s", "description": "Go package search" }, | |||
| 244 | - | "mdn": { "url": "https://developer.mozilla.org/en-US/search?q=%s", "description": "MDN Web Docs search" } | |||
| 245 | - | } | |||
| 246 | - | ``` | |||
| 247 | - | ||||
| 248 | - | #### Dmenu Integration | |||
| 249 | - | ```json | |||
| 250 | - | "dmenu": { | |||
| 251 | - | "max_history_items": 20, | |||
| 252 | - | "show_visit_count": true, | |||
| 253 | - | "show_last_visited": true, | |||
| 254 | - | "history_prefix": "🕒", | |||
| 255 | - | "shortcut_prefix": "🔍", | |||
| 256 | - | "url_prefix": "🌐", | |||
| 257 | - | "date_format": "2006-01-02 15:04", | |||
| 258 | - | "sort_by_visit_count": true | |||
| 259 | - | } | |||
| 260 | - | ``` | |||
| 261 | - | ||||
| 262 | - | #### Logging Configuration | |||
| 263 | - | ```json | |||
| 264 | - | "logging": { | |||
| 265 | - | "level": "info", | |||
| 266 | - | "format": "text", | |||
| 267 | - | "filename": "", | |||
| 268 | - | "max_size": 100, | |||
| 269 | - | "max_backups": 3, | |||
| 270 | - | "max_age": 7, | |||
| 271 | - | "compress": true | |||
| 272 | - | } | |||
| 273 | - | ``` | |||
| 274 | - | ||||
| 275 | - | #### Appearance Settings | |||
| 276 | - | ```json | |||
| 277 | - | "appearance": { | |||
| 278 | - | "color_scheme": "default", | |||
| 279 | - | "sans_font": "Fira Sans", | |||
| 280 | - | "serif_font": "Fira Sans", | |||
| 281 | - | "monospace_font": "Fira Code", | |||
| 282 | - | "default_font_size": 16, | |||
| 283 | "default_zoom": 1.2, | 224 | "default_zoom": 1.2, | ||
| 284 | - | "color_palette": { | 225 | + | "rendering_mode": "gpu", |
| 285 | - | "light": { | 226 | + | "search_shortcuts": { |
| 286 | - | "background": "#ffffff", | 227 | + | "g": { "url": "https://google.com/search?q=%s", "description": "Google" } |
| 287 | - | "surface": "#f5f5f5", | 228 | + | }, |
| 288 | - | "text": "#1a1a1a", | 229 | + | "workspace": { |
| 289 | - | "text_muted": "#6b7280", | 230 | + | "enable_zellij_controls": true, |
| 290 | - | "accent": "#3b82f6", | 231 | + | "popups": { "behavior": "split" } |
| 291 | - | "border": "#e5e7eb" | |||
| 292 | - | }, | |||
| 293 | - | "dark": { | |||
| 294 | - | "background": "#0a0a0a", | |||
| 295 | - | "surface": "#1a1a1a", | |||
| 296 | - | "text": "#e5e7eb", | |||
| 297 | - | "text_muted": "#9ca3af", | |||
| 298 | - | "accent": "#60a5fa", | |||
| 299 | - | "border": "#374151" | |||
| 300 | - | } | |||
| 301 | } | 232 | } | ||
| 302 | } | 233 | } | ||
| 303 | ``` | 234 | ``` | ||
| 304 | - | - `color_scheme`: `"prefer-dark"`, `"prefer-light"`, or `"default"` (follows system theme) | |||
| 305 | - | ||||
| 306 | - | #### Rendering Mode (GPU/CPU) | |||
| 307 | - | ```json | |||
| 308 | - | "rendering_mode": "auto" | |||
| 309 | - | ``` | |||
| 310 | - | - `auto`: Detect GPU availability and use GPU when available (default) | |||
| 311 | - | - `gpu`: Force GPU acceleration (Vulkan/OpenGL via GTK4) | |||
| 312 | - | - `cpu`: Force software rendering | |||
| 313 | - | ||||
| 314 | - | ### Environment Variables | |||
| 315 | - | All config values can be overridden with environment variables using the `DUMB_BROWSER_` prefix: | |||
| 316 | 235 | ||||
| 236 | + | Environment variable override: | |||
| 317 | ```bash | 237 | ```bash | ||
| 318 | - | # Database | 238 | + | DUMBER_RENDERING_MODE=cpu dumber |
| 319 | - | DUMB_BROWSER_DATABASE_PATH="./browser.db" | 239 | + | DUMB_BROWSER_LOGGING_LEVEL=debug dumber |
| 320 | - | DUMB_BROWSER_DATABASE_MAX_CONNECTIONS=5 | |||
| 321 | - | ||||
| 322 | - | # Rendering mode (special variable name) | |||
| 323 | - | DUMBER_RENDERING_MODE="gpu" | |||
| 324 | - | ||||
| 325 | - | # Dmenu settings | |||
| 326 | - | DUMB_BROWSER_DMENU_MAX_HISTORY_ITEMS=50 | |||
| 327 | - | DUMB_BROWSER_DMENU_SHOW_VISIT_COUNT=false | |||
| 328 | - | ||||
| 329 | - | # Logging | |||
| 330 | - | DUMB_BROWSER_LOGGING_LEVEL="debug" | |||
| 331 | - | DUMB_BROWSER_LOGGING_FORMAT="json" | |||
| 332 | ``` | 240 | ``` | ||
| 333 | 241 | ||||
| 334 | - | ### CLI Flags | 242 | + | **📖 Complete documentation**: See [docs/CONFIG.md](docs/CONFIG.md) for all available settings, defaults, and valid values. |
| 335 | - | The browse command supports additional runtime flags: | |||
| 336 | - | ```bash | |||
| 337 | - | dumber browse --rendering-mode=gpu https://example.com | |||
| 338 | - | ``` | |||
| 339 | 243 | ||||
| 340 | 244 | ||||
| 341 | ## Building With WebKitGTK 6 (GTK4) | 245 | ## Building With WebKitGTK 6 (GTK4) | ||
A docs/CONFIG.md +295 -0
| @@ -0,0 +1,295 @@ | |||
| 1 | + | # Configuration Reference | |
| 2 | + | ||
| 3 | + | **Primary format**: JSON | |
| 4 | + | **Location**: `~/.config/dumber/config.json` | |
| 5 | + | **Also supports**: YAML (`.yaml`) and TOML (`.toml`) | |
| 6 | + | **JSON Schema**: `~/.config/dumber/config.schema.json` (auto-generated) | |
| 7 | + | ||
| 8 | + | ## IDE Integration | |
| 9 | + | ||
| 10 | + | For autocompletion and validation in VS Code or other editors, add this to the top of your `config.json`: | |
| 11 | + | ||
| 12 | + | ```json | |
| 13 | + | { | |
| 14 | + | "$schema": "./config.schema.json", | |
| 15 | + | "default_zoom": 1.2, | |
| 16 | + | ... | |
| 17 | + | } | |
| 18 | + | ``` | |
| 19 | + | ||
| 20 | + | The schema is automatically generated when you first create a config file. | |
| 21 | + | ||
| 22 | + | ## Database | |
| 23 | + | ||
| 24 | + | | Key | Type | Default | Description | | |
| 25 | + | |-----|------|---------|-------------| | |
| 26 | + | | `database.path` | string | `~/.local/state/dumber/dumber.sqlite` | Database file path | | |
| 27 | + | ||
| 28 | + | ## History | |
| 29 | + | ||
| 30 | + | | Key | Type | Default | Valid Values | Description | | |
| 31 | + | |-----|------|---------|--------------|-------------| | |
| 32 | + | | `history.max_entries` | int | `10000` | > 0 | Maximum number of history entries | | |
| 33 | + | | `history.retention_period_days` | int | `365` | > 0 | Days to keep history (1 year) | | |
| 34 | + | | `history.cleanup_interval_days` | int | `1` | > 0 | How often to run cleanup | | |
| 35 | + | ||
| 36 | + | ## Search Shortcuts | |
| 37 | + | ||
| 38 | + | | Key | Type | Default | Description | | |
| 39 | + | |-----|------|---------|-------------| | |
| 40 | + | | `search_shortcuts` | map | See defaults | Map of shortcut aliases to URLs | | |
| 41 | + | ||
| 42 | + | **Default shortcuts:** | |
| 43 | + | ```json | |
| 44 | + | { | |
| 45 | + | "search_shortcuts": { | |
| 46 | + | "g": { | |
| 47 | + | "url": "https://google.com/search?q=%s", | |
| 48 | + | "description": "Google Search" | |
| 49 | + | }, | |
| 50 | + | "gh": { | |
| 51 | + | "url": "https://github.com/search?q=%s", | |
| 52 | + | "description": "GitHub" | |
| 53 | + | }, | |
| 54 | + | "yt": { | |
| 55 | + | "url": "https://youtube.com/results?search_query=%s", | |
| 56 | + | "description": "YouTube" | |
| 57 | + | } | |
| 58 | + | } | |
| 59 | + | } | |
| 60 | + | ``` | |
| 61 | + | ||
| 62 | + | ## Dmenu / Launcher | |
| 63 | + | ||
| 64 | + | | Key | Type | Default | Description | | |
| 65 | + | |-----|------|---------|-------------| | |
| 66 | + | | `dmenu.max_history_items` | int | `20` | Max items shown in launcher | | |
| 67 | + | | `dmenu.show_visit_count` | bool | `true` | Show visit counts | | |
| 68 | + | | `dmenu.show_last_visited` | bool | `true` | Show last visited dates | | |
| 69 | + | | `dmenu.history_prefix` | string | `"🕒"` | Prefix for history items | | |
| 70 | + | | `dmenu.shortcut_prefix` | string | `"🔍"` | Prefix for shortcuts | | |
| 71 | + | | `dmenu.url_prefix` | string | `"🌐"` | Prefix for URLs | | |
| 72 | + | | `dmenu.date_format` | string | `"2006-01-02 15:04"` | Go time format string | | |
| 73 | + | | `dmenu.sort_by_visit_count` | bool | `true` | Sort by popularity | | |
| 74 | + | ||
| 75 | + | ## Logging | |
| 76 | + | ||
| 77 | + | | Key | Type | Default | Valid Values | Description | | |
| 78 | + | |-----|------|---------|--------------|-------------| | |
| 79 | + | | `logging.level` | string | `"info"` | `debug`, `info`, `warn`, `error` | Log level | | |
| 80 | + | | `logging.format` | string | `"text"` | `text`, `json` | Log format | | |
| 81 | + | | `logging.filename` | string | `""` | any | Empty = stdout | | |
| 82 | + | | `logging.max_size` | int | `100` | > 0 | Max log size in MB | | |
| 83 | + | | `logging.max_backups` | int | `3` | >= 0 | Number of log backups | | |
| 84 | + | | `logging.max_age` | int | `7` | >= 0 | Days to keep logs | | |
| 85 | + | | `logging.compress` | bool | `true` | - | Compress old logs | | |
| 86 | + | | `logging.log_dir` | string | `~/.local/state/dumber/logs/` | any | Log directory | | |
| 87 | + | | `logging.enable_file_log` | bool | `true` | - | Enable file logging | | |
| 88 | + | | `logging.capture_stdout` | bool | `false` | - | Capture stdout to log | | |
| 89 | + | | `logging.capture_stderr` | bool | `false` | - | Capture stderr to log | | |
| 90 | + | | `logging.capture_c_output` | bool | `false` | - | Capture C/CGO output | | |
| 91 | + | | `logging.capture_console` | bool | `false` | - | Capture browser console | | |
| 92 | + | | `logging.debug_file` | string | `"debug.log"` | any | Debug log filename | | |
| 93 | + | | `logging.verbose_webkit` | bool | `false` | - | Verbose WebKit logs | | |
| 94 | + | ||
| 95 | + | ## Appearance | |
| 96 | + | ||
| 97 | + | | Key | Type | Default | Description | | |
| 98 | + | |-----|------|---------|-------------| | |
| 99 | + | | `appearance.sans_font` | string | `"Fira Sans"` | Sans-serif font | | |
| 100 | + | | `appearance.serif_font` | string | `"Fira Sans"` | Serif font | | |
| 101 | + | | `appearance.monospace_font` | string | `"Fira Code"` | Monospace font | | |
| 102 | + | | `appearance.default_font_size` | int | `16` | Font size in points | | |
| 103 | + | | `appearance.color_scheme` | string | `"default"` | `prefer-dark`, `prefer-light`, `default` | | |
| 104 | + | ||
| 105 | + | ### Color Palettes | |
| 106 | + | ||
| 107 | + | **Light palette:** | |
| 108 | + | ```json | |
| 109 | + | { | |
| 110 | + | "appearance": { | |
| 111 | + | "light_palette": { | |
| 112 | + | "background": "#f8f8f8", | |
| 113 | + | "surface": "#f2f2f2", | |
| 114 | + | "surface_variant": "#ececec", | |
| 115 | + | "text": "#1a1a1a", | |
| 116 | + | "muted": "#6e6e6e", | |
| 117 | + | "accent": "#404040", | |
| 118 | + | "border": "#d2d2d2" | |
| 119 | + | } | |
| 120 | + | } | |
| 121 | + | } | |
| 122 | + | ``` | |
| 123 | + | ||
| 124 | + | **Dark palette:** | |
| 125 | + | ```json | |
| 126 | + | { | |
| 127 | + | "appearance": { | |
| 128 | + | "dark_palette": { | |
| 129 | + | "background": "#0e0e0e", | |
| 130 | + | "surface": "#1a1a1a", | |
| 131 | + | "surface_variant": "#141414", | |
| 132 | + | "text": "#e4e4e4", | |
| 133 | + | "muted": "#848484", | |
| 134 | + | "accent": "#a8a8a8", | |
| 135 | + | "border": "#363636" | |
| 136 | + | } | |
| 137 | + | } | |
| 138 | + | } | |
| 139 | + | ``` | |
| 140 | + | ||
| 141 | + | ## Video Acceleration | |
| 142 | + | ||
| 143 | + | | Key | Type | Default | Description | | |
| 144 | + | |-----|------|---------|-------------| | |
| 145 | + | | `video_acceleration.enable_vaapi` | bool | `true` | Enable VA-API hardware accel | | |
| 146 | + | | `video_acceleration.auto_detect_gpu` | bool | `true` | Auto-detect GPU driver | | |
| 147 | + | | `video_acceleration.vaapi_driver_name` | string | `""` | Driver name (auto-detected) | | |
| 148 | + | | `video_acceleration.enable_all_drivers` | bool | `true` | Enable all VA-API drivers | | |
| 149 | + | | `video_acceleration.legacy_vaapi` | bool | `false` | Legacy VA-API mode | | |
| 150 | + | ||
| 151 | + | ## Codec Preferences | |
| 152 | + | ||
| 153 | + | | Key | Type | Default | Valid Values | Description | | |
| 154 | + | |-----|------|---------|--------------|-------------| | |
| 155 | + | | `codec_preferences.preferred_codecs` | string | `"av1,h264"` | Comma-separated | Codec priority order | | |
| 156 | + | | `codec_preferences.force_av1` | bool | `false` | - | Force AV1 codec | | |
| 157 | + | | `codec_preferences.block_vp9` | bool | `false` | - | Block VP9 codec | | |
| 158 | + | | `codec_preferences.block_vp8` | bool | `true` | - | Block VP8 codec | | |
| 159 | + | | `codec_preferences.av1_hardware_only` | bool | `false` | - | Disable AV1 software fallback | | |
| 160 | + | | `codec_preferences.disable_vp9_hardware` | bool | `false` | - | Disable VP9 hardware accel | | |
| 161 | + | | `codec_preferences.video_buffer_size_mb` | int | `16` | > 0 | Video buffer size in MB | | |
| 162 | + | | `codec_preferences.queue_buffer_time_sec` | int | `10` | > 0 | Queue buffer time in seconds | | |
| 163 | + | | `codec_preferences.custom_user_agent` | string | Chrome UA | any | Custom user agent string | | |
| 164 | + | | `codec_preferences.av1_max_resolution` | string | `"1080p"` | `720p`, `1080p`, `1440p`, `4k`, `unlimited` | Max AV1 resolution | | |
| 165 | + | | `codec_preferences.disable_twitch_codec_control` | bool | `true` | - | Disable codec control on Twitch | | |
| 166 | + | ||
| 167 | + | ## Debug Options | |
| 168 | + | ||
| 169 | + | | Key | Type | Default | Description | | |
| 170 | + | |-----|------|---------|-------------| | |
| 171 | + | | `debug.enable_webkit_debug` | bool | `false` | Enable WebKit debug logs | | |
| 172 | + | | `debug.webkit_debug_categories` | string | `"Network:preconnectTo,ContentFilters"` | Debug categories | | |
| 173 | + | | `debug.enable_filtering_debug` | bool | `false` | Content filter debug | | |
| 174 | + | | `debug.enable_webview_debug` | bool | `false` | WebView state debug | | |
| 175 | + | | `debug.log_webkit_crashes` | bool | `true` | Log WebKit crashes | | |
| 176 | + | | `debug.enable_script_debug` | bool | `false` | Script injection debug | | |
| 177 | + | | `debug.enable_general_debug` | bool | `false` | General debug mode | | |
| 178 | + | | `debug.enable_workspace_debug` | bool | `false` | Workspace navigation debug | | |
| 179 | + | | `debug.enable_focus_debug` | bool | `false` | Focus state debug | | |
| 180 | + | | `debug.enable_css_debug` | bool | `false` | CSS reconciler debug | | |
| 181 | + | | `debug.enable_focus_metrics` | bool | `false` | Focus metrics tracking | | |
| 182 | + | | `debug.enable_pane_close_debug` | bool | `false` | Pane close debug | | |
| 183 | + | ||
| 184 | + | ## Rendering & Zoom | |
| 185 | + | ||
| 186 | + | | Key | Type | Default | Valid Values | Description | | |
| 187 | + | |-----|------|---------|--------------|-------------| | |
| 188 | + | | `rendering_mode` | string | `"gpu"` | `auto`, `gpu`, `cpu` | Rendering mode | | |
| 189 | + | | `use_dom_zoom` | bool | `false` | - | Use DOM-based zoom | | |
| 190 | + | | `default_zoom` | float | `1.2` | > 0 | Default zoom level (120%) | | |
| 191 | + | ||
| 192 | + | ## Workspace Configuration | |
| 193 | + | ||
| 194 | + | | Key | Type | Default | Description | | |
| 195 | + | |-----|------|---------|-------------| | |
| 196 | + | | `workspace.enable_zellij_controls` | bool | `true` | Enable Zellij-style keybindings | | |
| 197 | + | ||
| 198 | + | ### Pane Mode | |
| 199 | + | ||
| 200 | + | | Key | Type | Default | Description | | |
| 201 | + | |-----|------|---------|-------------| | |
| 202 | + | | `workspace.pane_mode.activation_shortcut` | string | `"ctrl+p"` | Pane mode activation key | | |
| 203 | + | | `workspace.pane_mode.timeout_ms` | int | `3000` | Pane mode timeout (ms) | | |
| 204 | + | | `workspace.pane_mode.action_bindings` | map | See below | Pane mode key bindings | | |
| 205 | + | ||
| 206 | + | **Default pane mode bindings:** | |
| 207 | + | ```json | |
| 208 | + | { | |
| 209 | + | "workspace": { | |
| 210 | + | "pane_mode": { | |
| 211 | + | "action_bindings": { | |
| 212 | + | "arrowright": "split-right", | |
| 213 | + | "arrowleft": "split-left", | |
| 214 | + | "arrowup": "split-up", | |
| 215 | + | "arrowdown": "split-down", | |
| 216 | + | "r": "split-right", | |
| 217 | + | "l": "split-left", | |
| 218 | + | "u": "split-up", | |
| 219 | + | "d": "split-down", | |
| 220 | + | "x": "close-pane", | |
| 221 | + | "enter": "confirm", | |
| 222 | + | "escape": "cancel" | |
| 223 | + | } | |
| 224 | + | } | |
| 225 | + | } | |
| 226 | + | } | |
| 227 | + | ``` | |
| 228 | + | ||
| 229 | + | ### Tab Shortcuts | |
| 230 | + | ||
| 231 | + | | Key | Type | Default | Description | | |
| 232 | + | |-----|------|---------|-------------| | |
| 233 | + | | `workspace.tabs.new_tab` | string | `"ctrl+t"` | New tab shortcut | | |
| 234 | + | | `workspace.tabs.close_tab` | string | `"ctrl+w"` | Close tab shortcut | | |
| 235 | + | | `workspace.tabs.next_tab` | string | `"ctrl+tab"` | Next tab shortcut | | |
| 236 | + | | `workspace.tabs.previous_tab` | string | `"ctrl+shift+tab"` | Previous tab shortcut | | |
| 237 | + | ||
| 238 | + | ### Popup Behavior | |
| 239 | + | ||
| 240 | + | | Key | Type | Default | Valid Values | Description | | |
| 241 | + | |-----|------|---------|--------------|-------------| | |
| 242 | + | | `workspace.popups.behavior` | string | `"split"` | `split`, `stacked`, `tabbed`, `windowed` | Popup opening mode | | |
| 243 | + | | `workspace.popups.placement` | string | `"right"` | `right`, `left`, `top`, `bottom` | Split direction | | |
| 244 | + | | `workspace.popups.open_in_new_pane` | bool | `true` | - | Open popups in workspace | | |
| 245 | + | | `workspace.popups.follow_pane_context` | bool | `true` | - | Follow parent pane context | | |
| 246 | + | | `workspace.popups.blank_target_behavior` | string | `"pane"` | `pane`, `tab` | `_blank` target handling | | |
| 247 | + | | `workspace.popups.enable_smart_detection` | bool | `true` | - | Use WindowProperties for detection | | |
| 248 | + | | `workspace.popups.oauth_auto_close` | bool | `true` | - | Auto-close OAuth popups | | |
| 249 | + | ||
| 250 | + | ### Workspace Styling | |
| 251 | + | ||
| 252 | + | | Key | Type | Default | Description | | |
| 253 | + | |-----|------|---------|-------------| | |
| 254 | + | | `workspace.styling.border_width` | int | `2` | Border width in pixels | | |
| 255 | + | | `workspace.styling.border_color` | string | `"@theme_selected_bg_color"` | Border color (CSS or theme var) | | |
| 256 | + | | `workspace.styling.pane_mode_border_color` | string | `"#FFA500"` | Pane mode border color (orange) | | |
| 257 | + | | `workspace.styling.transition_duration` | int | `120` | Transition duration (ms) | | |
| 258 | + | | `workspace.styling.border_radius` | int | `0` | Border radius in pixels | | |
| 259 | + | ||
| 260 | + | ## Content Filtering | |
| 261 | + | ||
| 262 | + | | Key | Type | Default | Description | | |
| 263 | + | |-----|------|---------|-------------| | |
| 264 | + | | `content_filtering_whitelist` | array | See below | Domains to skip ad blocking | | |
| 265 | + | ||
| 266 | + | **Default whitelist:** | |
| 267 | + | ```json | |
| 268 | + | { | |
| 269 | + | "content_filtering_whitelist": [ | |
| 270 | + | "twitch.tv", | |
| 271 | + | "passport.twitch.tv", | |
| 272 | + | "gql.twitch.tv" | |
| 273 | + | ] | |
| 274 | + | } | |
| 275 | + | ``` | |
| 276 | + | ||
| 277 | + | ## Environment Variables | |
| 278 | + | ||
| 279 | + | All config values can be overridden via environment variables with the prefix `DUMB_BROWSER_`: | |
| 280 | + | ||
| 281 | + | ```bash | |
| 282 | + | # Database | |
| 283 | + | DUMB_BROWSER_DATABASE_PATH=/custom/path/db.sqlite | |
| 284 | + | ||
| 285 | + | # Rendering | |
| 286 | + | DUMBER_RENDERING_MODE=cpu | |
| 287 | + | DUMBER_DEFAULT_ZOOM=1.5 | |
| 288 | + | ||
| 289 | + | # Video/Codec | |
| 290 | + | DUMBER_VIDEO_ACCELERATION_ENABLE=true | |
| 291 | + | LIBVA_DRIVER_NAME=iHD | |
| 292 | + | DUMBER_PREFERRED_CODECS=av1,vp9,h264 | |
| 293 | + | ``` | |
| 294 | + | ||
| 295 | + | **Note:** Some video/codec env vars use `DUMBER_*` prefix and match GStreamer/VA-API conventions. | |
| @@ -0,0 +1,295 @@ | |||||
| 1 | + | # Configuration Reference | |||
| 2 | + | ||||
| 3 | + | **Primary format**: JSON | |||
| 4 | + | **Location**: `~/.config/dumber/config.json` | |||
| 5 | + | **Also supports**: YAML (`.yaml`) and TOML (`.toml`) | |||
| 6 | + | **JSON Schema**: `~/.config/dumber/config.schema.json` (auto-generated) | |||
| 7 | + | ||||
| 8 | + | ## IDE Integration | |||
| 9 | + | ||||
| 10 | + | For autocompletion and validation in VS Code or other editors, add this to the top of your `config.json`: | |||
| 11 | + | ||||
| 12 | + | ```json | |||
| 13 | + | { | |||
| 14 | + | "$schema": "./config.schema.json", | |||
| 15 | + | "default_zoom": 1.2, | |||
| 16 | + | ... | |||
| 17 | + | } | |||
| 18 | + | ``` | |||
| 19 | + | ||||
| 20 | + | The schema is automatically generated when you first create a config file. | |||
| 21 | + | ||||
| 22 | + | ## Database | |||
| 23 | + | ||||
| 24 | + | | Key | Type | Default | Description | | |||
| 25 | + | |-----|------|---------|-------------| | |||
| 26 | + | | `database.path` | string | `~/.local/state/dumber/dumber.sqlite` | Database file path | | |||
| 27 | + | ||||
| 28 | + | ## History | |||
| 29 | + | ||||
| 30 | + | | Key | Type | Default | Valid Values | Description | | |||
| 31 | + | |-----|------|---------|--------------|-------------| | |||
| 32 | + | | `history.max_entries` | int | `10000` | > 0 | Maximum number of history entries | | |||
| 33 | + | | `history.retention_period_days` | int | `365` | > 0 | Days to keep history (1 year) | | |||
| 34 | + | | `history.cleanup_interval_days` | int | `1` | > 0 | How often to run cleanup | | |||
| 35 | + | ||||
| 36 | + | ## Search Shortcuts | |||
| 37 | + | ||||
| 38 | + | | Key | Type | Default | Description | | |||
| 39 | + | |-----|------|---------|-------------| | |||
| 40 | + | | `search_shortcuts` | map | See defaults | Map of shortcut aliases to URLs | | |||
| 41 | + | ||||
| 42 | + | **Default shortcuts:** | |||
| 43 | + | ```json | |||
| 44 | + | { | |||
| 45 | + | "search_shortcuts": { | |||
| 46 | + | "g": { | |||
| 47 | + | "url": "https://google.com/search?q=%s", | |||
| 48 | + | "description": "Google Search" | |||
| 49 | + | }, | |||
| 50 | + | "gh": { | |||
| 51 | + | "url": "https://github.com/search?q=%s", | |||
| 52 | + | "description": "GitHub" | |||
| 53 | + | }, | |||
| 54 | + | "yt": { | |||
| 55 | + | "url": "https://youtube.com/results?search_query=%s", | |||
| 56 | + | "description": "YouTube" | |||
| 57 | + | } | |||
| 58 | + | } | |||
| 59 | + | } | |||
| 60 | + | ``` | |||
| 61 | + | ||||
| 62 | + | ## Dmenu / Launcher | |||
| 63 | + | ||||
| 64 | + | | Key | Type | Default | Description | | |||
| 65 | + | |-----|------|---------|-------------| | |||
| 66 | + | | `dmenu.max_history_items` | int | `20` | Max items shown in launcher | | |||
| 67 | + | | `dmenu.show_visit_count` | bool | `true` | Show visit counts | | |||
| 68 | + | | `dmenu.show_last_visited` | bool | `true` | Show last visited dates | | |||
| 69 | + | | `dmenu.history_prefix` | string | `"🕒"` | Prefix for history items | | |||
| 70 | + | | `dmenu.shortcut_prefix` | string | `"🔍"` | Prefix for shortcuts | | |||
| 71 | + | | `dmenu.url_prefix` | string | `"🌐"` | Prefix for URLs | | |||
| 72 | + | | `dmenu.date_format` | string | `"2006-01-02 15:04"` | Go time format string | | |||
| 73 | + | | `dmenu.sort_by_visit_count` | bool | `true` | Sort by popularity | | |||
| 74 | + | ||||
| 75 | + | ## Logging | |||
| 76 | + | ||||
| 77 | + | | Key | Type | Default | Valid Values | Description | | |||
| 78 | + | |-----|------|---------|--------------|-------------| | |||
| 79 | + | | `logging.level` | string | `"info"` | `debug`, `info`, `warn`, `error` | Log level | | |||
| 80 | + | | `logging.format` | string | `"text"` | `text`, `json` | Log format | | |||
| 81 | + | | `logging.filename` | string | `""` | any | Empty = stdout | | |||
| 82 | + | | `logging.max_size` | int | `100` | > 0 | Max log size in MB | | |||
| 83 | + | | `logging.max_backups` | int | `3` | >= 0 | Number of log backups | | |||
| 84 | + | | `logging.max_age` | int | `7` | >= 0 | Days to keep logs | | |||
| 85 | + | | `logging.compress` | bool | `true` | - | Compress old logs | | |||
| 86 | + | | `logging.log_dir` | string | `~/.local/state/dumber/logs/` | any | Log directory | | |||
| 87 | + | | `logging.enable_file_log` | bool | `true` | - | Enable file logging | | |||
| 88 | + | | `logging.capture_stdout` | bool | `false` | - | Capture stdout to log | | |||
| 89 | + | | `logging.capture_stderr` | bool | `false` | - | Capture stderr to log | | |||
| 90 | + | | `logging.capture_c_output` | bool | `false` | - | Capture C/CGO output | | |||
| 91 | + | | `logging.capture_console` | bool | `false` | - | Capture browser console | | |||
| 92 | + | | `logging.debug_file` | string | `"debug.log"` | any | Debug log filename | | |||
| 93 | + | | `logging.verbose_webkit` | bool | `false` | - | Verbose WebKit logs | | |||
| 94 | + | ||||
| 95 | + | ## Appearance | |||
| 96 | + | ||||
| 97 | + | | Key | Type | Default | Description | | |||
| 98 | + | |-----|------|---------|-------------| | |||
| 99 | + | | `appearance.sans_font` | string | `"Fira Sans"` | Sans-serif font | | |||
| 100 | + | | `appearance.serif_font` | string | `"Fira Sans"` | Serif font | | |||
| 101 | + | | `appearance.monospace_font` | string | `"Fira Code"` | Monospace font | | |||
| 102 | + | | `appearance.default_font_size` | int | `16` | Font size in points | | |||
| 103 | + | | `appearance.color_scheme` | string | `"default"` | `prefer-dark`, `prefer-light`, `default` | | |||
| 104 | + | ||||
| 105 | + | ### Color Palettes | |||
| 106 | + | ||||
| 107 | + | **Light palette:** | |||
| 108 | + | ```json | |||
| 109 | + | { | |||
| 110 | + | "appearance": { | |||
| 111 | + | "light_palette": { | |||
| 112 | + | "background": "#f8f8f8", | |||
| 113 | + | "surface": "#f2f2f2", | |||
| 114 | + | "surface_variant": "#ececec", | |||
| 115 | + | "text": "#1a1a1a", | |||
| 116 | + | "muted": "#6e6e6e", | |||
| 117 | + | "accent": "#404040", | |||
| 118 | + | "border": "#d2d2d2" | |||
| 119 | + | } | |||
| 120 | + | } | |||
| 121 | + | } | |||
| 122 | + | ``` | |||
| 123 | + | ||||
| 124 | + | **Dark palette:** | |||
| 125 | + | ```json | |||
| 126 | + | { | |||
| 127 | + | "appearance": { | |||
| 128 | + | "dark_palette": { | |||
| 129 | + | "background": "#0e0e0e", | |||
| 130 | + | "surface": "#1a1a1a", | |||
| 131 | + | "surface_variant": "#141414", | |||
| 132 | + | "text": "#e4e4e4", | |||
| 133 | + | "muted": "#848484", | |||
| 134 | + | "accent": "#a8a8a8", | |||
| 135 | + | "border": "#363636" | |||
| 136 | + | } | |||
| 137 | + | } | |||
| 138 | + | } | |||
| 139 | + | ``` | |||
| 140 | + | ||||
| 141 | + | ## Video Acceleration | |||
| 142 | + | ||||
| 143 | + | | Key | Type | Default | Description | | |||
| 144 | + | |-----|------|---------|-------------| | |||
| 145 | + | | `video_acceleration.enable_vaapi` | bool | `true` | Enable VA-API hardware accel | | |||
| 146 | + | | `video_acceleration.auto_detect_gpu` | bool | `true` | Auto-detect GPU driver | | |||
| 147 | + | | `video_acceleration.vaapi_driver_name` | string | `""` | Driver name (auto-detected) | | |||
| 148 | + | | `video_acceleration.enable_all_drivers` | bool | `true` | Enable all VA-API drivers | | |||
| 149 | + | | `video_acceleration.legacy_vaapi` | bool | `false` | Legacy VA-API mode | | |||
| 150 | + | ||||
| 151 | + | ## Codec Preferences | |||
| 152 | + | ||||
| 153 | + | | Key | Type | Default | Valid Values | Description | | |||
| 154 | + | |-----|------|---------|--------------|-------------| | |||
| 155 | + | | `codec_preferences.preferred_codecs` | string | `"av1,h264"` | Comma-separated | Codec priority order | | |||
| 156 | + | | `codec_preferences.force_av1` | bool | `false` | - | Force AV1 codec | | |||
| 157 | + | | `codec_preferences.block_vp9` | bool | `false` | - | Block VP9 codec | | |||
| 158 | + | | `codec_preferences.block_vp8` | bool | `true` | - | Block VP8 codec | | |||
| 159 | + | | `codec_preferences.av1_hardware_only` | bool | `false` | - | Disable AV1 software fallback | | |||
| 160 | + | | `codec_preferences.disable_vp9_hardware` | bool | `false` | - | Disable VP9 hardware accel | | |||
| 161 | + | | `codec_preferences.video_buffer_size_mb` | int | `16` | > 0 | Video buffer size in MB | | |||
| 162 | + | | `codec_preferences.queue_buffer_time_sec` | int | `10` | > 0 | Queue buffer time in seconds | | |||
| 163 | + | | `codec_preferences.custom_user_agent` | string | Chrome UA | any | Custom user agent string | | |||
| 164 | + | | `codec_preferences.av1_max_resolution` | string | `"1080p"` | `720p`, `1080p`, `1440p`, `4k`, `unlimited` | Max AV1 resolution | | |||
| 165 | + | | `codec_preferences.disable_twitch_codec_control` | bool | `true` | - | Disable codec control on Twitch | | |||
| 166 | + | ||||
| 167 | + | ## Debug Options | |||
| 168 | + | ||||
| 169 | + | | Key | Type | Default | Description | | |||
| 170 | + | |-----|------|---------|-------------| | |||
| 171 | + | | `debug.enable_webkit_debug` | bool | `false` | Enable WebKit debug logs | | |||
| 172 | + | | `debug.webkit_debug_categories` | string | `"Network:preconnectTo,ContentFilters"` | Debug categories | | |||
| 173 | + | | `debug.enable_filtering_debug` | bool | `false` | Content filter debug | | |||
| 174 | + | | `debug.enable_webview_debug` | bool | `false` | WebView state debug | | |||
| 175 | + | | `debug.log_webkit_crashes` | bool | `true` | Log WebKit crashes | | |||
| 176 | + | | `debug.enable_script_debug` | bool | `false` | Script injection debug | | |||
| 177 | + | | `debug.enable_general_debug` | bool | `false` | General debug mode | | |||
| 178 | + | | `debug.enable_workspace_debug` | bool | `false` | Workspace navigation debug | | |||
| 179 | + | | `debug.enable_focus_debug` | bool | `false` | Focus state debug | | |||
| 180 | + | | `debug.enable_css_debug` | bool | `false` | CSS reconciler debug | | |||
| 181 | + | | `debug.enable_focus_metrics` | bool | `false` | Focus metrics tracking | | |||
| 182 | + | | `debug.enable_pane_close_debug` | bool | `false` | Pane close debug | | |||
| 183 | + | ||||
| 184 | + | ## Rendering & Zoom | |||
| 185 | + | ||||
| 186 | + | | Key | Type | Default | Valid Values | Description | | |||
| 187 | + | |-----|------|---------|--------------|-------------| | |||
| 188 | + | | `rendering_mode` | string | `"gpu"` | `auto`, `gpu`, `cpu` | Rendering mode | | |||
| 189 | + | | `use_dom_zoom` | bool | `false` | - | Use DOM-based zoom | | |||
| 190 | + | | `default_zoom` | float | `1.2` | > 0 | Default zoom level (120%) | | |||
| 191 | + | ||||
| 192 | + | ## Workspace Configuration | |||
| 193 | + | ||||
| 194 | + | | Key | Type | Default | Description | | |||
| 195 | + | |-----|------|---------|-------------| | |||
| 196 | + | | `workspace.enable_zellij_controls` | bool | `true` | Enable Zellij-style keybindings | | |||
| 197 | + | ||||
| 198 | + | ### Pane Mode | |||
| 199 | + | ||||
| 200 | + | | Key | Type | Default | Description | | |||
| 201 | + | |-----|------|---------|-------------| | |||
| 202 | + | | `workspace.pane_mode.activation_shortcut` | string | `"ctrl+p"` | Pane mode activation key | | |||
| 203 | + | | `workspace.pane_mode.timeout_ms` | int | `3000` | Pane mode timeout (ms) | | |||
| 204 | + | | `workspace.pane_mode.action_bindings` | map | See below | Pane mode key bindings | | |||
| 205 | + | ||||
| 206 | + | **Default pane mode bindings:** | |||
| 207 | + | ```json | |||
| 208 | + | { | |||
| 209 | + | "workspace": { | |||
| 210 | + | "pane_mode": { | |||
| 211 | + | "action_bindings": { | |||
| 212 | + | "arrowright": "split-right", | |||
| 213 | + | "arrowleft": "split-left", | |||
| 214 | + | "arrowup": "split-up", | |||
| 215 | + | "arrowdown": "split-down", | |||
| 216 | + | "r": "split-right", | |||
| 217 | + | "l": "split-left", | |||
| 218 | + | "u": "split-up", | |||
| 219 | + | "d": "split-down", | |||
| 220 | + | "x": "close-pane", | |||
| 221 | + | "enter": "confirm", | |||
| 222 | + | "escape": "cancel" | |||
| 223 | + | } | |||
| 224 | + | } | |||
| 225 | + | } | |||
| 226 | + | } | |||
| 227 | + | ``` | |||
| 228 | + | ||||
| 229 | + | ### Tab Shortcuts | |||
| 230 | + | ||||
| 231 | + | | Key | Type | Default | Description | | |||
| 232 | + | |-----|------|---------|-------------| | |||
| 233 | + | | `workspace.tabs.new_tab` | string | `"ctrl+t"` | New tab shortcut | | |||
| 234 | + | | `workspace.tabs.close_tab` | string | `"ctrl+w"` | Close tab shortcut | | |||
| 235 | + | | `workspace.tabs.next_tab` | string | `"ctrl+tab"` | Next tab shortcut | | |||
| 236 | + | | `workspace.tabs.previous_tab` | string | `"ctrl+shift+tab"` | Previous tab shortcut | | |||
| 237 | + | ||||
| 238 | + | ### Popup Behavior | |||
| 239 | + | ||||
| 240 | + | | Key | Type | Default | Valid Values | Description | | |||
| 241 | + | |-----|------|---------|--------------|-------------| | |||
| 242 | + | | `workspace.popups.behavior` | string | `"split"` | `split`, `stacked`, `tabbed`, `windowed` | Popup opening mode | | |||
| 243 | + | | `workspace.popups.placement` | string | `"right"` | `right`, `left`, `top`, `bottom` | Split direction | | |||
| 244 | + | | `workspace.popups.open_in_new_pane` | bool | `true` | - | Open popups in workspace | | |||
| 245 | + | | `workspace.popups.follow_pane_context` | bool | `true` | - | Follow parent pane context | | |||
| 246 | + | | `workspace.popups.blank_target_behavior` | string | `"pane"` | `pane`, `tab` | `_blank` target handling | | |||
| 247 | + | | `workspace.popups.enable_smart_detection` | bool | `true` | - | Use WindowProperties for detection | | |||
| 248 | + | | `workspace.popups.oauth_auto_close` | bool | `true` | - | Auto-close OAuth popups | | |||
| 249 | + | ||||
| 250 | + | ### Workspace Styling | |||
| 251 | + | ||||
| 252 | + | | Key | Type | Default | Description | | |||
| 253 | + | |-----|------|---------|-------------| | |||
| 254 | + | | `workspace.styling.border_width` | int | `2` | Border width in pixels | | |||
| 255 | + | | `workspace.styling.border_color` | string | `"@theme_selected_bg_color"` | Border color (CSS or theme var) | | |||
| 256 | + | | `workspace.styling.pane_mode_border_color` | string | `"#FFA500"` | Pane mode border color (orange) | | |||
| 257 | + | | `workspace.styling.transition_duration` | int | `120` | Transition duration (ms) | | |||
| 258 | + | | `workspace.styling.border_radius` | int | `0` | Border radius in pixels | | |||
| 259 | + | ||||
| 260 | + | ## Content Filtering | |||
| 261 | + | ||||
| 262 | + | | Key | Type | Default | Description | | |||
| 263 | + | |-----|------|---------|-------------| | |||
| 264 | + | | `content_filtering_whitelist` | array | See below | Domains to skip ad blocking | | |||
| 265 | + | ||||
| 266 | + | **Default whitelist:** | |||
| 267 | + | ```json | |||
| 268 | + | { | |||
| 269 | + | "content_filtering_whitelist": [ | |||
| 270 | + | "twitch.tv", | |||
| 271 | + | "passport.twitch.tv", | |||
| 272 | + | "gql.twitch.tv" | |||
| 273 | + | ] | |||
| 274 | + | } | |||
| 275 | + | ``` | |||
| 276 | + | ||||
| 277 | + | ## Environment Variables | |||
| 278 | + | ||||
| 279 | + | All config values can be overridden via environment variables with the prefix `DUMB_BROWSER_`: | |||
| 280 | + | ||||
| 281 | + | ```bash | |||
| 282 | + | # Database | |||
| 283 | + | DUMB_BROWSER_DATABASE_PATH=/custom/path/db.sqlite | |||
| 284 | + | ||||
| 285 | + | # Rendering | |||
| 286 | + | DUMBER_RENDERING_MODE=cpu | |||
| 287 | + | DUMBER_DEFAULT_ZOOM=1.5 | |||
| 288 | + | ||||
| 289 | + | # Video/Codec | |||
| 290 | + | DUMBER_VIDEO_ACCELERATION_ENABLE=true | |||
| 291 | + | LIBVA_DRIVER_NAME=iHD | |||
| 292 | + | DUMBER_PREFERRED_CODECS=av1,vp9,h264 | |||
| 293 | + | ``` | |||
| 294 | + | ||||
| 295 | + | **Note:** Some video/codec env vars use `DUMBER_*` prefix and match GStreamer/VA-API conventions. | |||