Skip to main content
Flow Browser provides a comprehensive keyboard shortcut system that can be customized to match your workflow. All shortcuts support both Windows/Linux (Ctrl) and macOS (Cmd) modifier keys.

Default Shortcuts

The default keyboard shortcuts are defined in src/main/modules/shortcuts.ts:4-96.

Tabs

ShortcutActionCategory
Cmd/Ctrl + TNew TabTabs
Cmd/Ctrl + WClose TabTab
Cmd/Ctrl + RReloadTab
Cmd/Ctrl + Shift + RForce ReloadTab
Cmd/Ctrl + Shift + CCopy URLTab
F12Toggle DevToolsTab
Cmd/Ctrl + FFind in PageTab
ShortcutActionCategory
Cmd/Ctrl + LeftGo BackNavigation
Cmd/Ctrl + RightGo ForwardNavigation
Cmd/Ctrl + LToggle Command PaletteNavigation

Browser

ShortcutActionCategory
Cmd/Ctrl + ,Open SettingsBrowser
Cmd/Ctrl + NNew WindowBrowser
Cmd/Ctrl + Shift + WClose WindowBrowser
Cmd/Ctrl + SToggle SidebarBrowser

Spaces

ShortcutAction
Ctrl + 1Switch to Space 1
Ctrl + 2Switch to Space 2
Ctrl + 3Switch to Space 3
Ctrl + 9Switch to Space 9
Space shortcuts are dynamically generated based on the number of Spaces you have. See Spaces for more details.

Shortcut System Architecture

The shortcut system consists of two main components:

1. Shortcut Definitions

Shortcuts are defined as typed objects:
interface ShortcutAction {
  id: string;           // Unique identifier (e.g., "tabs.new")
  name: string;         // Display name (e.g., "New Tab")
  shortcut: string;     // Key combination (e.g., "CommandOrControl+T")
  category: string;     // Group name (e.g., "Tabs")
}
From src/main/modules/shortcuts.ts:4.

2. Shortcut Storage

Modified shortcuts are persisted to disk:
interface ModifiedShortcutData {
  newShortcut: string;  // The customized key combination
}
Stored using the datastore at src/main/saving/shortcuts.ts:12:
export const ShortcutsDataStore = getDatastore('shortcuts');

Customizing Shortcuts

Shortcuts can be customized programmatically through the shortcuts saving system.

Update a Shortcut

import { updateModifiedShortcut } from '@/saving/shortcuts';

const success = await updateModifiedShortcut('tabs.new', {
  newShortcut: 'CommandOrControl+Shift+T'
});
From src/main/saving/shortcuts.ts:49-68.

Reset a Shortcut

Restore a shortcut to its default value:
import { resetModifiedShortcut } from '@/saving/shortcuts';

const success = await resetModifiedShortcut('tabs.new');

Reset All Shortcuts

Restore all shortcuts to defaults:
import { resetAllModifiedShortcuts } from '@/saving/shortcuts';

const success = await resetAllModifiedShortcuts();
From src/main/saving/shortcuts.ts:89-98.

Getting Shortcuts

Retrieve shortcut information for display or execution:

Get All Shortcuts

import { getShortcuts } from '@/modules/shortcuts';

const shortcuts = getShortcuts();
// Returns array with both original and modified shortcuts
The returned shortcuts include:
interface ShortcutWithOriginal extends ShortcutAction {
  originalShortcut: string;  // Default shortcut
  shortcut: string;          // Current (possibly modified) shortcut
}

Get Single Shortcut

import { getShortcut, getCurrentShortcut } from '@/modules/shortcuts';

// Get full shortcut object
const shortcut = getShortcut('tabs.new');

// Get just the key combination
const keys = getCurrentShortcut('tabs.new');
// Returns: "CommandOrControl+T"
From src/main/modules/shortcuts.ts:117-129.

Shortcut Format

Shortcuts use Electron’s accelerator syntax:

Modifiers

  • CommandOrControl - Cmd on macOS, Ctrl on Windows/Linux
  • Command or Cmd - macOS only
  • Control or Ctrl - All platforms
  • Alt or Option - Alt key
  • Shift - Shift key
  • Super - Windows key on Windows/Linux, Command key on macOS

Key Codes

  • Letter keys: A-Z
  • Number keys: 0-9
  • Function keys: F1-F24
  • Arrow keys: Left, Right, Up, Down
  • Special keys: Space, Tab, Enter, Escape, Backspace, etc.

Examples

'CommandOrControl+T'           // Ctrl+T on Windows, Cmd+T on macOS
'Shift+CommandOrControl+R'     // Ctrl+Shift+R / Cmd+Shift+R
'F12'                          // Function key F12
'CommandOrControl+Left'        // Ctrl+Left Arrow / Cmd+Left Arrow

Shortcut Events

The shortcuts system emits events when shortcuts change:
type ShortcutsEvents = {
  'shortcuts-changed': [];
}

export const shortcutsEmitter = new TypedEventEmitter<ShortcutsEvents>();
From src/main/saving/shortcuts.ts:15-18. Listen for changes:
import { shortcutsEmitter } from '@/saving/shortcuts';

shortcutsEmitter.on('shortcuts-changed', () => {
  // Shortcuts have been modified, reload them
  const updated = getShortcuts();
});

Shortcut Categories

Shortcuts are organized into categories for better organization:
Operations that create new tabs
  • New Tab
Operations on the current tab
  • Close Tab
  • Reload
  • Force Reload
  • Copy URL
  • Toggle DevTools
  • Find in Page
Browser-wide operations
  • Open Settings
  • New Window
  • Close Window
  • Toggle Sidebar

Typed Shortcut IDs

The shortcut system uses TypeScript to ensure type safety:
type ShortcutId = 
  | 'tabs.new'
  | 'tab.copyUrl'
  | 'tab.reload'
  | 'tab.forceReload'
  | 'tab.close'
  | 'tab.toggleDevTools'
  | 'navigation.goBack'
  | 'navigation.goForward'
  | 'navigation.toggleCommandPalette'
  | 'browser.openSettings'
  | 'browser.newWindow'
  | 'browser.closeWindow'
  | 'browser.toggleSidebar'
  | 'tab.findInPage';
Use type-safe shortcut IDs:
import { getShortcutByTypedId } from '@/modules/shortcuts';

const shortcut = getShortcutByTypedId('tabs.new');
// TypeScript ensures the ID is valid
From src/main/modules/shortcuts.ts:98-123.

Shortcut Loading

Shortcuts are loaded automatically on startup:
async function loadShortcuts() {
  const rawModifiedShortcuts = await ShortcutsDataStore.getFullData();
  
  for (const key of Object.keys(rawModifiedShortcuts)) {
    const rawModifiedShortcutData = rawModifiedShortcuts[key];
    const parseResult = ModifiedShortcutData(rawModifiedShortcutData);
    if (!(parseResult instanceof type.errors)) {
      modifiedShortcuts.set(key, parseResult);
    }
  }
  
  shortcutsEmitter.emit('shortcuts-changed');
}

loadShortcuts();
From src/main/saving/shortcuts.ts:24-46.

Shortcut Validation

Custom shortcuts are validated using the arktype schema:
const ModifiedShortcutData = type({
  newShortcut: 'string'
});

const parseResult = ModifiedShortcutData(rawModifiedShortcutData);
if (parseResult instanceof type.errors) {
  // Invalid data, reject the change
  return false;
}
This ensures only valid shortcut data is persisted.

Implementation Details

Internal Variables

The shortcuts system maintains an in-memory cache:
const modifiedShortcuts: Map<string, ModifiedShortcutData> = new Map();
From src/main/saving/shortcuts.ts:21.

Merging Default and Modified

When retrieving shortcuts, the system merges defaults with modifications:
const updatedShortcuts = shortcuts.map((shortcut) => {
  const modifiedShortcutData = modifiedShortcutsData.find(
    ({ id }) => id === shortcut.id
  );
  return {
    ...shortcut,
    originalShortcut: shortcut.shortcut,
    shortcut: modifiedShortcutData?.newShortcut || shortcut.shortcut
  };
});
From src/main/modules/shortcuts.ts:105-112.

Best Practices

Avoid Conflicts

Don’t assign the same shortcut to multiple actions

Use Modifiers

Always include at least one modifier key (Cmd/Ctrl/Alt)

Be Consistent

Follow platform conventions (Cmd on macOS, Ctrl on Windows)

Test Thoroughly

Verify shortcuts work in all contexts (tabs, settings, etc.)
  • Tabs - Many shortcuts operate on tabs
  • Spaces - Space switching shortcuts
  • Extensions - Extensions may register their own shortcuts

Build docs developers (and LLMs) love