v0.27.2 5960dd8

schema.go RawHistoryFolder

1package config
2
3// Config represents the complete configuration for dumber.
4type Config struct {
5	Database        DatabaseConfig            `mapstructure:"database" yaml:"database" toml:"database"`
6	History         HistoryConfig             `mapstructure:"history" yaml:"history" toml:"history"`
7	SearchShortcuts map[string]SearchShortcut `mapstructure:"search_shortcuts" yaml:"search_shortcuts" toml:"search_shortcuts"`
8	// DefaultSearchEngine is the URL template for the default search engine (must contain %s placeholder)
9	DefaultSearchEngine string           `mapstructure:"default_search_engine" yaml:"default_search_engine" toml:"default_search_engine"`
10	Dmenu               DmenuConfig      `mapstructure:"dmenu" yaml:"dmenu" toml:"dmenu"`
11	Logging             LoggingConfig    `mapstructure:"logging" yaml:"logging" toml:"logging"`
12	Appearance          AppearanceConfig `mapstructure:"appearance" yaml:"appearance" toml:"appearance"`
13	Debug               DebugConfig      `mapstructure:"debug" yaml:"debug" toml:"debug"`
14	// DefaultWebpageZoom sets the default zoom level for pages without saved zoom settings (1.0 = 100%, 1.2 = 120%)
15	DefaultWebpageZoom float64 `mapstructure:"default_webpage_zoom" yaml:"default_webpage_zoom" toml:"default_webpage_zoom"`
16	// DefaultUIScale sets the default UI scale for GTK widgets (1.0 = 100%, 2.0 = 200%)
17	DefaultUIScale float64 `mapstructure:"default_ui_scale" yaml:"default_ui_scale" toml:"default_ui_scale"`
18	// Workspace defines workspace, pane, and tab handling behavior.
19	Workspace WorkspaceConfig `mapstructure:"workspace" yaml:"workspace" toml:"workspace"`
20	// Session controls session persistence and restoration.
21	Session SessionConfig `mapstructure:"session" yaml:"session" toml:"session"`
22	// ContentFiltering controls ad blocking and content filtering
23	ContentFiltering ContentFilteringConfig `mapstructure:"content_filtering" yaml:"content_filtering" toml:"content_filtering"`
24	// Clipboard controls clipboard-related behavior
25	Clipboard ClipboardConfig `mapstructure:"clipboard" yaml:"clipboard" toml:"clipboard"`
26	// Omnibox controls the omnibox behavior (initial history display)
27	Omnibox OmniboxConfig `mapstructure:"omnibox" yaml:"omnibox" toml:"omnibox"`
28	// Rendering controls WebKit, GTK and compositor behavior.
29	Rendering RenderingConfig `mapstructure:"rendering" yaml:"rendering" toml:"rendering"`
30	// Privacy controls cookie acceptance and tracking prevention.
31	Privacy PrivacyConfig `mapstructure:"privacy" yaml:"privacy" toml:"privacy"`
32	// Media controls video playback and hardware acceleration
33	Media MediaConfig `mapstructure:"media" yaml:"media" toml:"media"`
34	// Runtime configures optional runtime overrides (e.g., /opt prefix for WebKitGTK/GTK).
35	Runtime RuntimeConfig `mapstructure:"runtime" yaml:"runtime" toml:"runtime"`
36	// Performance holds internal performance tuning options (not exposed in UI).
37	Performance PerformanceConfig `mapstructure:"performance" yaml:"performance" toml:"performance"`
38	// Update controls automatic update checking and downloading.
39	Update UpdateConfig `mapstructure:"update" yaml:"update" toml:"update"`
40	// Downloads configures file download behavior.
41	Downloads DownloadsConfig `mapstructure:"downloads" yaml:"downloads" toml:"downloads"`
42}
43
44// RenderingMode selects GPU vs CPU rendering.
45type RenderingMode string
46
47const (
48	RenderingModeAuto RenderingMode = "auto"
49	RenderingModeGPU  RenderingMode = "gpu"
50	RenderingModeCPU  RenderingMode = "cpu"
51)
52
53// CookiePolicy controls cookie acceptance behavior.
54type CookiePolicy string
55
56const (
57	// CookiePolicyAlways accepts all cookies.
58	CookiePolicyAlways CookiePolicy = "always"
59	// CookiePolicyNoThirdParty blocks third-party cookies.
60	CookiePolicyNoThirdParty CookiePolicy = "no_third_party"
61	// CookiePolicyNever blocks all cookies.
62	CookiePolicyNever CookiePolicy = "never"
63)
64
65// GSKRendererMode controls the GTK Scene Kit renderer selection.
66type GSKRendererMode string
67
68const (
69	GSKRendererAuto   GSKRendererMode = "auto"
70	GSKRendererOpenGL GSKRendererMode = "opengl"
71	GSKRendererVulkan GSKRendererMode = "vulkan"
72	GSKRendererCairo  GSKRendererMode = "cairo"
73)
74
75// RenderingConfig controls WebKit and GTK/GSK rendering behavior.
76type RenderingConfig struct {
77	// Mode controls GPU/CPU rendering selection for WebKit (auto, gpu, cpu).
78	Mode RenderingMode `mapstructure:"mode" yaml:"mode" toml:"mode"`
79
80	// DisableDMABufRenderer disables DMA-BUF accelerated renderer.
81	// Env: WEBKIT_DISABLE_DMABUF_RENDERER
82	DisableDMABufRenderer bool `mapstructure:"disable_dmabuf_renderer" yaml:"disable_dmabuf_renderer" toml:"disable_dmabuf_renderer"`
83
84	// ForceCompositingMode forces accelerated compositing.
85	// Env: WEBKIT_FORCE_COMPOSITING_MODE
86	ForceCompositingMode bool `mapstructure:"force_compositing_mode" yaml:"force_compositing_mode" toml:"force_compositing_mode"`
87
88	// DisableCompositingMode disables accelerated compositing.
89	// Env: WEBKIT_DISABLE_COMPOSITING_MODE
90	DisableCompositingMode bool `mapstructure:"disable_compositing_mode" yaml:"disable_compositing_mode" toml:"disable_compositing_mode"`
91
92	// GSKRenderer overrides GTK Scene Kit renderer selection.
93	// Env: GSK_RENDERER
94	GSKRenderer GSKRendererMode `mapstructure:"gsk_renderer" yaml:"gsk_renderer" toml:"gsk_renderer"`
95
96	// DisableMipmaps disables mipmap generation.
97	// Env: GSK_GPU_DISABLE=mipmap
98	DisableMipmaps bool `mapstructure:"disable_mipmaps" yaml:"disable_mipmaps" toml:"disable_mipmaps"`
99
100	// PreferGL forces OpenGL over GLES.
101	// Env: GDK_DEBUG=gl-prefer-gl
102	PreferGL bool `mapstructure:"prefer_gl" yaml:"prefer_gl" toml:"prefer_gl"`
103
104	// DrawCompositingIndicators shows compositing layer borders and repaint counters.
105	DrawCompositingIndicators bool `mapstructure:"draw_compositing_indicators" yaml:"draw_compositing_indicators" toml:"draw_compositing_indicators"` //nolint:lll // struct tags exceed lll limit
106
107	// ShowFPS displays WebKit FPS counter.
108	// Env: WEBKIT_SHOW_FPS
109	ShowFPS bool `mapstructure:"show_fps" yaml:"show_fps" toml:"show_fps"`
110
111	// SampleMemory enables memory sampling.
112	// Env: WEBKIT_SAMPLE_MEMORY
113	SampleMemory bool `mapstructure:"sample_memory" yaml:"sample_memory" toml:"sample_memory"`
114
115	// DebugFrames enables frame timing debug output.
116	// Env: GDK_DEBUG=frames
117	DebugFrames bool `mapstructure:"debug_frames" yaml:"debug_frames" toml:"debug_frames"`
118}
119
120// PrivacyConfig controls cookie behavior and tracking prevention.
121type PrivacyConfig struct {
122	// CookiePolicy controls cookie acceptance behavior.
123	// Values: "always", "no_third_party", "never"
124	CookiePolicy CookiePolicy `mapstructure:"cookie_policy" yaml:"cookie_policy" toml:"cookie_policy"`
125	// ITPEnabled enables Intelligent Tracking Prevention.
126	ITPEnabled bool `mapstructure:"itp_enabled" yaml:"itp_enabled" toml:"itp_enabled"`
127}
128
129// HardwareDecodingMode controls video hardware acceleration.
130type HardwareDecodingMode string
131
132const (
133	// HardwareDecodingAuto lets GStreamer choose (hw preferred, sw fallback)
134	HardwareDecodingAuto HardwareDecodingMode = "auto"
135	// HardwareDecodingForce requires hardware decoding (fails if unavailable)
136	HardwareDecodingForce HardwareDecodingMode = "force"
137	// HardwareDecodingDisable uses software decoding only
138	HardwareDecodingDisable HardwareDecodingMode = "disable"
139)
140
141// GLRenderingMode controls OpenGL API selection for video rendering.
142type GLRenderingMode string
143
144const (
145	// GLRenderingModeAuto lets GStreamer choose the best GL API
146	GLRenderingModeAuto GLRenderingMode = "auto"
147	// GLRenderingModeGLES2 forces GLES2 (better for some mobile/embedded GPUs)
148	GLRenderingModeGLES2 GLRenderingMode = "gles2"
149	// GLRenderingModeGL3 forces OpenGL 3.x desktop
150	GLRenderingModeGL3 GLRenderingMode = "gl3"
151	// GLRenderingModeNone disables GL-based rendering
152	GLRenderingModeNone GLRenderingMode = "none"
153)
154
155// PerformanceProfile selects preset performance tuning settings.
156type PerformanceProfile string
157
158const (
159	// ProfileDefault uses WebKit defaults (no tuning applied).
160	ProfileDefault PerformanceProfile = "default"
161	// ProfileLite reduces resource usage for low-RAM systems.
162	ProfileLite PerformanceProfile = "lite"
163	// ProfileMax maximizes responsiveness for heavy pages (GitHub PRs, etc).
164	ProfileMax PerformanceProfile = "max"
165	// ProfileCustom allows full control over individual performance settings.
166	ProfileCustom PerformanceProfile = "custom"
167)
168
169// ThemeDefault is the default theme setting (follows system).
170const ThemeDefault = "default"
171
172const (
173	// ThemePreferDark explicitly selects dark theme.
174	ThemePreferDark = "prefer-dark"
175	// ThemePreferLight explicitly selects light theme.
176	ThemePreferLight = "prefer-light"
177)
178
179// MediaConfig holds video playback and hardware acceleration preferences.
180type MediaConfig struct {
181	// HardwareDecodingMode controls hardware vs software video decoding
182	// Values: "auto" (default), "force", "disable"
183	HardwareDecodingMode HardwareDecodingMode `mapstructure:"hardware_decoding" yaml:"hardware_decoding" toml:"hardware_decoding"`
184	// PreferAV1 prioritizes AV1 codec (most efficient) when available
185	PreferAV1 bool `mapstructure:"prefer_av1" yaml:"prefer_av1" toml:"prefer_av1"`
186	// ShowDiagnosticsOnStartup shows media capability warnings at startup
187	ShowDiagnosticsOnStartup bool `mapstructure:"show_diagnostics" yaml:"show_diagnostics" toml:"show_diagnostics"`
188	// ForceVSync forces vertical sync for video playback (may help with tearing)
189	ForceVSync bool `mapstructure:"force_vsync" yaml:"force_vsync" toml:"force_vsync"`
190	// GLRenderingMode controls OpenGL API selection for video rendering
191	// Values: "auto" (default), "gles2", "gl3", "none"
192	GLRenderingMode GLRenderingMode `mapstructure:"gl_rendering_mode" yaml:"gl_rendering_mode" toml:"gl_rendering_mode"`
193	// GStreamerDebugLevel sets GStreamer debug verbosity (0=off, 1-5=increasing verbosity)
194	GStreamerDebugLevel int `mapstructure:"gstreamer_debug_level" yaml:"gstreamer_debug_level" toml:"gstreamer_debug_level"`
195}
196
197// RuntimeConfig holds optional runtime overrides.
198type RuntimeConfig struct {
199	// Prefix points to a custom runtime prefix (e.g., /opt/webkitgtk).
200	// This is used to influence pkg-config lookup and dynamic library loading.
201	Prefix string `mapstructure:"prefix" yaml:"prefix" toml:"prefix"`
202}
203
204// DatabaseConfig holds database-related configuration.
205type DatabaseConfig struct {
206	Path string `mapstructure:"path" yaml:"path" toml:"path"`
207}
208
209// HistoryConfig holds history-related configuration.
210type HistoryConfig struct {
211	MaxEntries          int `mapstructure:"max_entries" yaml:"max_entries" toml:"max_entries"`
212	RetentionPeriodDays int `mapstructure:"retention_period_days" yaml:"retention_period_days" toml:"retention_period_days"`
213	CleanupIntervalDays int `mapstructure:"cleanup_interval_days" yaml:"cleanup_interval_days" toml:"cleanup_interval_days"`
214}
215
216// PerformanceConfig holds internal performance tuning options.
217// These are not exposed in dumb://config UI but can be set in config file.
218type PerformanceConfig struct {
219	// Profile selects a preset performance configuration.
220	// Values: "default" (no tuning), "lite" (low RAM), "max" (heavy pages), "custom" (manual control)
221	// When profile is not "custom", individual tuning fields below are ignored and computed from the profile.
222	// Default: "default"
223	Profile PerformanceProfile `mapstructure:"profile" yaml:"profile" toml:"profile"`
224
225	// ZoomCacheSize is the number of domain zoom levels to cache in memory.
226	// Higher values reduce database queries but use more memory.
227	// Default: 256 domains (~20KB memory)
228	ZoomCacheSize int `mapstructure:"zoom_cache_size" yaml:"zoom_cache_size" toml:"zoom_cache_size"`
229
230	// WebViewPoolPrewarmCount is the number of WebViews to pre-create at startup.
231	// Higher values speed up initial tab creation but use more memory.
232	// Default: 4 (custom mode), computed from profile otherwise
233	WebViewPoolPrewarmCount int `mapstructure:"webview_pool_prewarm_count" yaml:"webview_pool_prewarm_count" toml:"webview_pool_prewarm_count"` //nolint:lll // struct tags must stay on one line
234
235	// --- Skia rendering threads (env vars) ---
236	// NOTE: Fields below only apply when Profile is "custom".
237	// SkiaCPUPaintingThreads sets WEBKIT_SKIA_CPU_PAINTING_THREADS.
238	// Default: 0 (unset, uses WebKit default)
239	SkiaCPUPaintingThreads int `mapstructure:"skia_cpu_painting_threads" yaml:"skia_cpu_painting_threads" toml:"skia_cpu_painting_threads"` //nolint:lll // struct tags must stay on one line
240
241	// SkiaGPUPaintingThreads sets WEBKIT_SKIA_GPU_PAINTING_THREADS.
242	// Default: -1 (unset). Value 0 disables GPU tile painting.
243	SkiaGPUPaintingThreads int `mapstructure:"skia_gpu_painting_threads" yaml:"skia_gpu_painting_threads" toml:"skia_gpu_painting_threads"` //nolint:lll // struct tags must stay on one line
244
245	// SkiaEnableCPURendering forces CPU rendering via WEBKIT_SKIA_ENABLE_CPU_RENDERING=1.
246	// Default: false
247	SkiaEnableCPURendering bool `mapstructure:"skia_enable_cpu_rendering" yaml:"skia_enable_cpu_rendering" toml:"skia_enable_cpu_rendering"` //nolint:lll // struct tags must stay on one line
248
249	// --- Web process memory pressure ---
250	// WebProcessMemoryLimitMB sets memory limit in MB for web processes.
251	// Default: 0 (unset, uses WebKit default: system RAM capped at 3GB)
252	WebProcessMemoryLimitMB int `mapstructure:"web_process_memory_limit_mb" yaml:"web_process_memory_limit_mb" toml:"web_process_memory_limit_mb"` //nolint:lll // struct tags must stay on one line
253
254	// WebProcessMemoryPollIntervalSec sets poll interval for memory checks.
255	// Default: 0 (unset, uses WebKit default: 30 seconds)
256	WebProcessMemoryPollIntervalSec float64 `mapstructure:"web_process_memory_poll_interval_sec" yaml:"web_process_memory_poll_interval_sec" toml:"web_process_memory_poll_interval_sec"` //nolint:lll // struct tags must stay on one line
257
258	// WebProcessMemoryConservativeThreshold sets threshold for conservative memory release.
259	// Valid: (0, 1). Default: 0 (unset, uses WebKit default: 0.33)
260	WebProcessMemoryConservativeThreshold float64 `mapstructure:"web_process_memory_conservative_threshold" yaml:"web_process_memory_conservative_threshold" toml:"web_process_memory_conservative_threshold"` //nolint:lll // struct tags must stay on one line
261
262	// WebProcessMemoryStrictThreshold sets threshold for strict memory release.
263	// Valid: (0, 1). Default: 0 (unset, uses WebKit default: 0.5)
264	WebProcessMemoryStrictThreshold float64 `mapstructure:"web_process_memory_strict_threshold" yaml:"web_process_memory_strict_threshold" toml:"web_process_memory_strict_threshold"` //nolint:lll // struct tags must stay on one line
265
266	// --- Network process memory pressure ---
267	// NetworkProcessMemoryLimitMB sets memory limit in MB for network process.
268	// Default: 0 (unset)
269	NetworkProcessMemoryLimitMB int `mapstructure:"network_process_memory_limit_mb" yaml:"network_process_memory_limit_mb" toml:"network_process_memory_limit_mb"` //nolint:lll // struct tags must stay on one line
270
271	// NetworkProcessMemoryPollIntervalSec sets poll interval for memory checks.
272	// Default: 0 (unset)
273	NetworkProcessMemoryPollIntervalSec float64 `mapstructure:"network_process_memory_poll_interval_sec" yaml:"network_process_memory_poll_interval_sec" toml:"network_process_memory_poll_interval_sec"` //nolint:lll // struct tags must stay on one line
274
275	// NetworkProcessMemoryConservativeThreshold sets threshold for conservative memory release.
276	// Valid: (0, 1). Default: 0 (unset)
277	NetworkProcessMemoryConservativeThreshold float64 `mapstructure:"network_process_memory_conservative_threshold" yaml:"network_process_memory_conservative_threshold" toml:"network_process_memory_conservative_threshold"` //nolint:lll // struct tags must stay on one line
278
279	// NetworkProcessMemoryStrictThreshold sets threshold for strict memory release.
280	// Valid: (0, 1). Default: 0 (unset)
281	NetworkProcessMemoryStrictThreshold float64 `mapstructure:"network_process_memory_strict_threshold" yaml:"network_process_memory_strict_threshold" toml:"network_process_memory_strict_threshold"` //nolint:lll // struct tags must stay on one line
282}
283
284// SearchShortcut represents a search shortcut configuration.
285type SearchShortcut struct {
286	URL         string `mapstructure:"url" toml:"url" yaml:"url" json:"url"`
287	Description string `mapstructure:"description" toml:"description" yaml:"description" json:"description"`
288}
289
290// ShortcutURLs returns a simple map of shortcut keys to URL templates.
291// This is useful for passing to url.BuildSearchURL.
292func (c *Config) ShortcutURLs() map[string]string {
293	result := make(map[string]string, len(c.SearchShortcuts))
294	for key, shortcut := range c.SearchShortcuts {
295		result[key] = shortcut.URL
296	}
297	return result
298}
299
300// DmenuConfig holds dmenu/rofi integration configuration.
301type DmenuConfig struct {
302	MaxHistoryDays   int    `mapstructure:"max_history_days" yaml:"max_history_days" toml:"max_history_days"`
303	ShowVisitCount   bool   `mapstructure:"show_visit_count" yaml:"show_visit_count" toml:"show_visit_count"`
304	ShowLastVisited  bool   `mapstructure:"show_last_visited" yaml:"show_last_visited" toml:"show_last_visited"`
305	HistoryPrefix    string `mapstructure:"history_prefix" yaml:"history_prefix" toml:"history_prefix"`
306	ShortcutPrefix   string `mapstructure:"shortcut_prefix" yaml:"shortcut_prefix" toml:"shortcut_prefix"`
307	URLPrefix        string `mapstructure:"url_prefix" yaml:"url_prefix" toml:"url_prefix"`
308	DateFormat       string `mapstructure:"date_format" yaml:"date_format" toml:"date_format"`
309	SortByVisitCount bool   `mapstructure:"sort_by_visit_count" yaml:"sort_by_visit_count" toml:"sort_by_visit_count"`
310}
311
312// LoggingConfig holds logging configuration.
313type LoggingConfig struct {
314	Level  string `mapstructure:"level" yaml:"level" toml:"level"`
315	Format string `mapstructure:"format" yaml:"format" toml:"format"`
316	MaxAge int    `mapstructure:"max_age" yaml:"max_age" toml:"max_age"`
317
318	// File output configuration
319	LogDir        string `mapstructure:"log_dir" yaml:"log_dir" toml:"log_dir"`
320	EnableFileLog bool   `mapstructure:"enable_file_log" yaml:"enable_file_log" toml:"enable_file_log"`
321
322	// Capture browser console to logs
323	CaptureConsole bool `mapstructure:"capture_console" yaml:"capture_console" toml:"capture_console" json:"capture_console"`
324
325	// Capture GTK4/WebKitGTK6 messages to session logs
326	CaptureGTKLogs bool `mapstructure:"capture_gtk_logs" yaml:"capture_gtk_logs" toml:"capture_gtk_logs" json:"capture_gtk_logs"`
327}
328
329// AppearanceConfig holds UI/rendering preferences.
330type AppearanceConfig struct {
331	// Default fonts for pages that do not specify fonts.
332	SansFont      string `mapstructure:"sans_font" yaml:"sans_font" toml:"sans_font"`
333	SerifFont     string `mapstructure:"serif_font" yaml:"serif_font" toml:"serif_font"`
334	MonospaceFont string `mapstructure:"monospace_font" yaml:"monospace_font" toml:"monospace_font"`
335	// Default font size in CSS pixels (approx).
336	DefaultFontSize int          `mapstructure:"default_font_size" yaml:"default_font_size" toml:"default_font_size"`
337	LightPalette    ColorPalette `mapstructure:"light_palette" yaml:"light_palette" toml:"light_palette"`
338	DarkPalette     ColorPalette `mapstructure:"dark_palette" yaml:"dark_palette" toml:"dark_palette"`
339	// ColorScheme controls the initial theme preference: "prefer-dark", "prefer-light", or "default" (follows system)
340	ColorScheme string `mapstructure:"color_scheme" yaml:"color_scheme" toml:"color_scheme"`
341}
342
343// ColorPalette contains semantic color tokens for light/dark themes.
344type ColorPalette struct {
345	Background     string `mapstructure:"background" yaml:"background" toml:"background" json:"background"`
346	Surface        string `mapstructure:"surface" yaml:"surface" toml:"surface" json:"surface"`
347	SurfaceVariant string `mapstructure:"surface_variant" yaml:"surface_variant" toml:"surface_variant" json:"surface_variant"`
348	Text           string `mapstructure:"text" yaml:"text" toml:"text" json:"text"`
349	Muted          string `mapstructure:"muted" yaml:"muted" toml:"muted" json:"muted"`
350	Accent         string `mapstructure:"accent" yaml:"accent" toml:"accent" json:"accent"`
351	Border         string `mapstructure:"border" yaml:"border" toml:"border" json:"border"`
352}
353
354// ContentFilteringConfig holds content filtering and ad blocking preferences
355type ContentFilteringConfig struct {
356	// Enabled controls whether ad blocking is active (default: true)
357	Enabled bool `mapstructure:"enabled" yaml:"enabled" toml:"enabled"`
358	// AutoUpdate controls whether filters are automatically updated (default: true)
359	AutoUpdate bool `mapstructure:"auto_update" yaml:"auto_update" toml:"auto_update"`
360	// Note: Filters are downloaded from bnema/ublock-webkit-filters GitHub releases
361	// Note: Whitelist is managed via database (content_whitelist table)
362}
363
364// ClipboardConfig holds clipboard-related behavior preferences
365type ClipboardConfig struct {
366	// AutoCopyOnSelection automatically copies selected text to clipboard (zellij-style).
367	// When enabled, selecting text in a webview immediately copies it to clipboard.
368	// Does not apply to text selection in input fields or textareas.
369	// Default: true
370	AutoCopyOnSelection bool `mapstructure:"auto_copy_on_selection" yaml:"auto_copy_on_selection" toml:"auto_copy_on_selection" json:"autoCopyOnSelection"` //nolint:lll // struct tags must stay on one line
371}
372
373// OmniboxConfig holds omnibox behavior preferences
374type OmniboxConfig struct {
375	// InitialBehavior controls what to show when omnibox opens with empty input
376	// Values: "recent" (recent visits), "most_visited" (most visited sites), "none" (nothing)
377	InitialBehavior string `mapstructure:"initial_behavior" yaml:"initial_behavior" toml:"initial_behavior"`
378	// AutoOpenOnNewPane opens the omnibox automatically when a new pane is created.
379	// Default: false
380	AutoOpenOnNewPane bool `mapstructure:"auto_open_on_new_pane" yaml:"auto_open_on_new_pane" toml:"auto_open_on_new_pane"`
381}
382
383// DebugConfig holds debug and troubleshooting options
384type DebugConfig struct {
385	// Enable browser developer tools (F12, Inspect Element in context menu)
386	EnableDevTools bool `mapstructure:"enable_devtools" yaml:"enable_devtools" toml:"enable_devtools"`
387}
388
389// UpdateConfig holds automatic update settings.
390type UpdateConfig struct {
391	// EnableOnStartup enables checking for updates when the browser starts.
392	// Default: true
393	EnableOnStartup bool `mapstructure:"enable_on_startup" yaml:"enable_on_startup" toml:"enable_on_startup"`
394	// AutoDownload automatically downloads updates in the background.
395	// When enabled, updates are applied on browser exit.
396	// Default: false
397	AutoDownload bool `mapstructure:"auto_download" yaml:"auto_download" toml:"auto_download"`
398	// NotifyOnNewSettings shows a toast notification on startup when new config settings are available.
399	// Default: true
400	NotifyOnNewSettings bool `mapstructure:"notify_on_new_settings" yaml:"notify_on_new_settings" toml:"notify_on_new_settings"`
401}
402
403// DownloadsConfig holds file download preferences.
404type DownloadsConfig struct {
405	// Path is the directory where downloads are saved.
406	// Empty string means use XDG_DOWNLOAD_DIR or ~/Downloads.
407	Path string `mapstructure:"path" yaml:"path" toml:"path"`
408}
409
410// WorkspaceConfig captures layout, pane, and tab behavior preferences.
411type WorkspaceConfig struct {
412	// NewPaneURL is the URL loaded when creating a new empty pane/tab.
413	// Default: "about:blank"
414	NewPaneURL string `mapstructure:"new_pane_url" yaml:"new_pane_url" toml:"new_pane_url"`
415	// PaneMode defines modal pane behavior and bindings.
416	PaneMode PaneModeConfig `mapstructure:"pane_mode" yaml:"pane_mode" toml:"pane_mode" json:"pane_mode"`
417	// TabMode defines modal tab behavior and bindings (Alt+T).
418	TabMode TabModeConfig `mapstructure:"tab_mode" yaml:"tab_mode" toml:"tab_mode" json:"tab_mode"`
419	// ResizeMode defines modal pane resizing behavior and bindings (Ctrl+N).
420	ResizeMode ResizeModeConfig `mapstructure:"resize_mode" yaml:"resize_mode" toml:"resize_mode" json:"resize_mode"`
421	// Shortcuts holds global (non-modal) keyboard shortcuts.
422	Shortcuts GlobalShortcutsConfig `mapstructure:"shortcuts" yaml:"shortcuts" toml:"shortcuts" json:"shortcuts"`
423	// FloatingPane configures workspace-level floating pane behavior.
424	FloatingPane FloatingPaneConfig `mapstructure:"floating_pane" yaml:"floating_pane" toml:"floating_pane" json:"floating_pane"`
425	// TabBarPosition determines tab bar placement: "top" or "bottom".
426	TabBarPosition string `mapstructure:"tab_bar_position" yaml:"tab_bar_position" toml:"tab_bar_position" json:"tab_bar_position"`
427	// HideTabBarWhenSingleTab hides the tab bar when only one tab exists.
428	HideTabBarWhenSingleTab bool `mapstructure:"hide_tab_bar_when_single_tab" yaml:"hide_tab_bar_when_single_tab" toml:"hide_tab_bar_when_single_tab" json:"hide_tab_bar_when_single_tab"` //nolint:lll // struct tags must stay on one line
429	// SwitchToTabOnMove controls whether moving a pane to another tab switches focus to that tab.
430	// Default: true
431	SwitchToTabOnMove bool `mapstructure:"switch_to_tab_on_move" yaml:"switch_to_tab_on_move" toml:"switch_to_tab_on_move" json:"switch_to_tab_on_move"` //nolint:lll // struct tags must stay on one line
432	// Popups configures default popup placement rules.
433	Popups PopupBehaviorConfig `mapstructure:"popups" yaml:"popups" toml:"popups" json:"popups"`
434	// Styling configures workspace visual appearance.
435	Styling WorkspaceStylingConfig `mapstructure:"styling" yaml:"styling" toml:"styling" json:"styling"`
436}
437
438// ActionBinding defines a keybinding with optional description.
439type ActionBinding struct {
440	Keys []string `mapstructure:"keys" yaml:"keys" toml:"keys" json:"keys"`
441	Desc string   `mapstructure:"desc" yaml:"desc" toml:"desc" json:"desc,omitempty"`
442}
443
444// PaneModeConfig defines modal behavior for pane management.
445type PaneModeConfig struct {
446	ActivationShortcut  string                   `mapstructure:"activation_shortcut" yaml:"activation_shortcut" toml:"activation_shortcut" json:"activation_shortcut"` //nolint:lll // struct tags must stay on one line
447	TimeoutMilliseconds int                      `mapstructure:"timeout_ms" yaml:"timeout_ms" toml:"timeout_ms" json:"timeout_ms"`
448	Actions             map[string]ActionBinding `mapstructure:"actions" yaml:"actions" toml:"actions" json:"actions"`
449}
450
451// GetKeyBindings returns an inverted map for O(1) key→action lookup.
452// This is built from the action→keys structure in the config.
453func (p *PaneModeConfig) GetKeyBindings() map[string]string {
454	keyToAction := make(map[string]string)
455	for action, binding := range p.Actions {
456		for _, key := range binding.Keys {
457			keyToAction[key] = action
458		}
459	}
460	return keyToAction
461}
462
463// TabModeConfig defines modal behavior for tab management (Zellij-style).
464type TabModeConfig struct {
465	ActivationShortcut  string                   `mapstructure:"activation_shortcut" yaml:"activation_shortcut" toml:"activation_shortcut" json:"activation_shortcut"` //nolint:lll // struct tags must stay on one line
466	TimeoutMilliseconds int                      `mapstructure:"timeout_ms" yaml:"timeout_ms" toml:"timeout_ms" json:"timeout_ms"`
467	Actions             map[string]ActionBinding `mapstructure:"actions" yaml:"actions" toml:"actions" json:"actions"`
468}
469
470// GetKeyBindings returns an inverted map for O(1) key→action lookup.
471// This is built from the action→keys structure in the config.
472func (t *TabModeConfig) GetKeyBindings() map[string]string {
473	keyToAction := make(map[string]string)
474	for action, binding := range t.Actions {
475		for _, key := range binding.Keys {
476			keyToAction[key] = action
477		}
478	}
479	return keyToAction
480}
481
482// ResizeModeConfig defines modal behavior for resizing panes (Zellij-style).
483type ResizeModeConfig struct {
484	ActivationShortcut  string                   `mapstructure:"activation_shortcut" yaml:"activation_shortcut" toml:"activation_shortcut" json:"activation_shortcut"` //nolint:lll // struct tags must stay on one line
485	TimeoutMilliseconds int                      `mapstructure:"timeout_ms" yaml:"timeout_ms" toml:"timeout_ms" json:"timeout_ms"`
486	StepPercent         float64                  `mapstructure:"step_percent" yaml:"step_percent" toml:"step_percent" json:"step_percent"`
487	MinPanePercent      float64                  `mapstructure:"min_pane_percent" yaml:"min_pane_percent" toml:"min_pane_percent" json:"min_pane_percent"` //nolint:lll // struct tags must stay on one line
488	Actions             map[string]ActionBinding `mapstructure:"actions" yaml:"actions" toml:"actions" json:"actions"`
489}
490
491// GetKeyBindings returns an inverted map for O(1) key→action lookup.
492// This is built from the action→keys structure in the config.
493func (r *ResizeModeConfig) GetKeyBindings() map[string]string {
494	keyToAction := make(map[string]string)
495	for action, binding := range r.Actions {
496		for _, key := range binding.Keys {
497			keyToAction[key] = action
498		}
499	}
500	return keyToAction
501}
502
503// GlobalShortcutsConfig defines global shortcuts (always active, not modal).
504type GlobalShortcutsConfig struct {
505	Actions map[string]ActionBinding `mapstructure:"actions" yaml:"actions" toml:"actions" json:"actions"`
506}
507
508// FloatingPaneConfig defines persistent floating pane behavior.
509type FloatingPaneConfig struct {
510	WidthPct  float64                        `mapstructure:"width_pct" yaml:"width_pct" toml:"width_pct" json:"width_pct"`
511	HeightPct float64                        `mapstructure:"height_pct" yaml:"height_pct" toml:"height_pct" json:"height_pct"`
512	Profiles  map[string]FloatingPaneProfile `mapstructure:"profiles" yaml:"profiles" toml:"profiles" json:"profiles"`
513}
514
515// FloatingPaneProfile defines a shortcut profile that opens a URL in the floating pane.
516type FloatingPaneProfile struct {
517	Keys []string `mapstructure:"keys" yaml:"keys" toml:"keys" json:"keys"`
518	URL  string   `mapstructure:"url" yaml:"url" toml:"url" json:"url"`
519	Desc string   `mapstructure:"desc" yaml:"desc" toml:"desc" json:"desc,omitempty"`
520}
521
522// GetKeyBindings returns an inverted map for O(1) key→action lookup.
523func (g *GlobalShortcutsConfig) GetKeyBindings() map[string]string {
524	keyToAction := make(map[string]string)
525	for action, binding := range g.Actions {
526		for _, key := range binding.Keys {
527			keyToAction[key] = action
528		}
529	}
530	return keyToAction
531}
532
533// PopupBehavior defines how popup windows should be opened
534type PopupBehavior string
535
536const (
537	// PopupBehaviorSplit opens popups in a split pane (default)
538	PopupBehaviorSplit PopupBehavior = "split"
539	// PopupBehaviorStacked opens popups in a stacked pane
540	PopupBehaviorStacked PopupBehavior = "stacked"
541	// PopupBehaviorTabbed opens popups as a new tab
542	PopupBehaviorTabbed PopupBehavior = "tabbed"
543	// PopupBehaviorWindowed opens popups in a new workspace window
544	PopupBehaviorWindowed PopupBehavior = "windowed"
545)
546
547// PopupBehaviorConfig defines handling for popup windows.
548type PopupBehaviorConfig struct {
549	// Behavior determines how popups are opened (split/stacked/tabbed/windowed)
550	Behavior PopupBehavior `mapstructure:"behavior" yaml:"behavior" toml:"behavior" json:"behavior"`
551
552	// Placement specifies direction for split behavior ("right", "left", "top", "bottom")
553	// Only used when Behavior is "split"
554	Placement string `mapstructure:"placement" yaml:"placement" toml:"placement" json:"placement"`
555
556	// OpenInNewPane controls whether popups are opened in workspace or blocked
557	OpenInNewPane bool `mapstructure:"open_in_new_pane" yaml:"open_in_new_pane" toml:"open_in_new_pane" json:"open_in_new_pane"`
558
559	// FollowPaneContext determines if popup placement follows parent pane context
560	FollowPaneContext bool `mapstructure:"follow_pane_context" yaml:"follow_pane_context" toml:"follow_pane_context" json:"follow_pane_context"` //nolint:lll // struct tags must stay on one line
561
562	// BlankTargetBehavior determines how target="_blank" links are opened
563	// Accepted values: "split", "stacked" (default), "tabbed"
564	// This is separate from Behavior which controls JavaScript popups
565	BlankTargetBehavior string `mapstructure:"blank_target_behavior" yaml:"blank_target_behavior" toml:"blank_target_behavior" json:"blank_target_behavior"` //nolint:lll // struct tags must stay on one line
566
567	// EnableSmartDetection uses WebKitWindowProperties to detect popup vs tab intents
568	EnableSmartDetection bool `mapstructure:"enable_smart_detection" yaml:"enable_smart_detection" toml:"enable_smart_detection" json:"enable_smart_detection"` //nolint:lll // struct tags must stay on one line
569
570	// OAuthAutoClose enables auto-closing OAuth popups after successful auth redirects
571	OAuthAutoClose bool `mapstructure:"oauth_auto_close" yaml:"oauth_auto_close" toml:"oauth_auto_close" json:"oauth_auto_close"`
572}
573
574// WorkspaceStylingConfig defines visual styling for workspace panes.
575type WorkspaceStylingConfig struct {
576	// BorderWidth in pixels for active pane borders (overlay)
577	BorderWidth int `mapstructure:"border_width" yaml:"border_width" toml:"border_width" json:"border_width"`
578	// BorderColor for focused panes (CSS color value or theme variable)
579	BorderColor string `mapstructure:"border_color" yaml:"border_color" toml:"border_color" json:"border_color"`
580
581	// ModeBorderWidth in pixels for all mode indicator borders (pane, tab, session, resize)
582	ModeBorderWidth int `mapstructure:"mode_border_width" yaml:"mode_border_width" toml:"mode_border_width" json:"mode_border_width"` //nolint:lll // struct tags must stay on one line
583
584	// PaneModeColor for pane mode indicator (border and toaster). Defaults to "#4A90E2" (blue)
585	PaneModeColor string `mapstructure:"pane_mode_color" yaml:"pane_mode_color" toml:"pane_mode_color" json:"pane_mode_color"` //nolint:lll // struct tags must stay on one line
586	// TabModeColor for tab mode indicator (border and toaster). Defaults to "#FFA500" (orange)
587	TabModeColor string `mapstructure:"tab_mode_color" yaml:"tab_mode_color" toml:"tab_mode_color" json:"tab_mode_color"` //nolint:lll // struct tags must stay on one line
588	// SessionModeColor for session mode indicator (border and toaster). Defaults to "#9B59B6" (purple)
589	SessionModeColor string `mapstructure:"session_mode_color" yaml:"session_mode_color" toml:"session_mode_color" json:"session_mode_color"` //nolint:lll // struct tags must stay on one line
590	// ResizeModeColor for resize mode indicator (border and toaster). Defaults to "#00D4AA" (teal)
591	ResizeModeColor string `mapstructure:"resize_mode_color" yaml:"resize_mode_color" toml:"resize_mode_color" json:"resize_mode_color"` //nolint:lll // struct tags must stay on one line
592
593	// ModeIndicatorToasterEnabled shows a toaster notification when modal modes are active.
594	// Default: true
595	ModeIndicatorToasterEnabled bool `mapstructure:"mode_indicator_toaster_enabled" yaml:"mode_indicator_toaster_enabled" toml:"mode_indicator_toaster_enabled" json:"mode_indicator_toaster_enabled"` //nolint:lll // struct tags must stay on one line
596
597	// TransitionDuration in milliseconds for border animations
598	TransitionDuration int `mapstructure:"transition_duration" yaml:"transition_duration" toml:"transition_duration" json:"transition_duration"` //nolint:lll // struct tags must stay on one line
599}
600
601// SessionConfig holds session persistence settings.
602type SessionConfig struct {
603	// AutoRestore automatically restores the last session on startup.
604	// Default: false
605	AutoRestore bool `mapstructure:"auto_restore" yaml:"auto_restore" toml:"auto_restore" json:"auto_restore"`
606
607	// SnapshotIntervalMs is the minimum interval between snapshots in milliseconds.
608	// Default: 5000
609	SnapshotIntervalMs int `mapstructure:"snapshot_interval_ms" yaml:"snapshot_interval_ms" toml:"snapshot_interval_ms" json:"snapshot_interval_ms"` //nolint:lll // struct tags must stay on one line
610
611	// MaxExitedSessions is the maximum number of exited sessions to keep.
612	// Default: 50
613	MaxExitedSessions int `mapstructure:"max_exited_sessions" yaml:"max_exited_sessions" toml:"max_exited_sessions" json:"max_exited_sessions"` //nolint:lll // struct tags must stay on one line
614
615	// MaxExitedSessionAgeDays is the maximum age in days for exited sessions.
616	// Sessions older than this will be automatically deleted on startup.
617	// Default: 7
618	MaxExitedSessionAgeDays int `mapstructure:"max_exited_session_age_days" yaml:"max_exited_session_age_days" toml:"max_exited_session_age_days" json:"max_exited_session_age_days"` //nolint:lll // struct tags must stay on one line
619
620	// SessionMode defines modal behavior for session management (Ctrl+O).
621	SessionMode SessionModeConfig `mapstructure:"session_mode" yaml:"session_mode" toml:"session_mode" json:"session_mode"`
622}
623
624// SessionModeConfig defines modal behavior for session management.
625type SessionModeConfig struct {
626	ActivationShortcut  string                   `mapstructure:"activation_shortcut" yaml:"activation_shortcut" toml:"activation_shortcut" json:"activation_shortcut"` //nolint:lll // struct tags must stay on one line
627	TimeoutMilliseconds int                      `mapstructure:"timeout_ms" yaml:"timeout_ms" toml:"timeout_ms" json:"timeout_ms"`
628	Actions             map[string]ActionBinding `mapstructure:"actions" yaml:"actions" toml:"actions" json:"actions"`
629}
630
631// GetKeyBindings returns an inverted map for O(1) key→action lookup.
632// This is built from the action→keys structure in the config.
633func (s *SessionModeConfig) GetKeyBindings() map[string]string {
634	keyToAction := make(map[string]string)
635	for action, binding := range s.Actions {
636		for _, key := range binding.Keys {
637			keyToAction[key] = action
638		}
639	}
640	return keyToAction
641}

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