Skip to main content
Glide Browser uses a modal editing system inspired by Vim, where different modes change how keyboard input is interpreted. This allows for efficient keyboard-driven browsing without conflicts between navigation and text input.

Built-in Modes

Glide comes with six built-in modes, each designed for specific tasks:
The default mode for browsing and navigation. Most keybindings are active in this mode.Purpose: Navigate pages, follow links, manage tabs, and trigger browser actionsCommon keybindings:
  • f - Show hints for clickable elements
  • gg / G - Scroll to top/bottom
  • <Space>r - Reload page (using leader key)
  • : - Open command line
Switch to normal: Press <Esc> from most other modes

Operator-Pending Mode

There’s also a special op-pending mode used internally for Vim-style operators:
Operator-Pending Mode is entered after pressing an operator key like d (delete) or c (change). The next motion determines what text to operate on.Example: dw deletes to the end of the word - d enters op-pending, then w executes the motion.

Mode Switching

Modes are changed using the mode_change command:
// Switch to insert mode
glide.keymaps.set("normal", "i", "mode_change insert --automove=left");

// Switch to ignore mode from multiple modes
glide.keymaps.set(["normal", "insert", "visual"], "<S-Esc>", "mode_change ignore");

// Return to normal from insert/visual/op-pending
glide.keymaps.set(["insert", "visual", "op-pending"], "<Esc>", "mode_change normal");

Checking Current Mode

Access the current mode via the context API:
if (glide.ctx.mode === "insert") {
  // Do something specific to insert mode
}

console.log("Current mode:", glide.ctx.mode);

Caret Appearance

Each mode can configure the caret (cursor) style:
A filled block cursor covering the entire character.Used in: normal, hint, op-pending modes

Custom Modes

You can register your own custom modes for specialized workflows:
1

Declare the mode type

First, declare the mode in the TypeScript type system:
declare global {
  interface GlideModes {
    leap: "leap";
  }
}
2

Register the mode at runtime

Register the mode with Glide and specify the caret style:
glide.modes.register('leap', { caret: 'block' });
3

Define keybindings for the mode

Set up keybindings specific to your custom mode:
// Enter the mode
glide.keymaps.set("normal", "<leader>l", "mode_change leap");

// Exit the mode
glide.keymaps.set("leap", "<Esc>", "mode_change normal");

// Mode-specific bindings
glide.keymaps.set("leap", "s", async () => {
  // Your leap logic here
});
Custom modes must be both type-declared AND registered at runtime. Missing either step will cause errors.

Mode Change Events

React to mode changes using autocmds:
// Called when entering visual mode from any mode
glide.autocmds.create("ModeChanged", "*:visual", ({ old_mode, new_mode }) => {
  console.log(`Entered visual mode from ${old_mode}`);
});

// Called when leaving visual mode
glide.autocmds.create("ModeChanged", "visual:*", ({ old_mode, new_mode }) => {
  console.log(`Left visual mode, now in ${new_mode}`);
});

// Called on any mode change
glide.autocmds.create("ModeChanged", "*", ({ old_mode, new_mode }) => {
  console.log(`Mode changed: ${old_mode}${new_mode}`);
});

// Specific transition
glide.autocmds.create("ModeChanged", "normal:insert", ({ old_mode, new_mode }) => {
  console.log("Started editing");
});

List All Modes

Get an array of all registered modes:
const modes = glide.modes.list();
console.log("Available modes:", modes);
// ["normal", "insert", "visual", "ignore", "command", "op-pending", "hint"]

Source Code References

  • Mode registration: src/glide/browser/base/content/browser-api.mts:886-897
  • Mode type definitions: src/glide/browser/base/content/glide.d.ts:1118-1125
  • Hint mode setup: src/glide/browser/base/content/plugins/hints.mts:19
  • Mode switching keybindings: src/glide/browser/base/content/plugins/keymaps.mts:27-84