Skip to main content
The glide.autocmds API allows you to register callbacks that are automatically triggered in response to specific events.

Methods

create()

Create an autocmd that responds to browser events.
glide.autocmds.create<Event extends AutocmdEvent>(
  event: Event,
  pattern: AutocmdPatterns[Event],
  callback: (args: AutocmdArgs[Event]) => void
): void

UrlEnter

Triggered when the focused URL changes. This includes:
  1. URL changes within the same tab
  2. Switching tabs
  3. Navigating back/forward in history

Signature

glide.autocmds.create(
  'UrlEnter',
  pattern: RegExp | { hostname?: string },
  callback: (args: { url: string; tab_id: number }) => void
): void

Parameters

pattern
RegExp | { hostname?: string }
required
Match against URLs:
  • RegExp - Matches against the full URL string
  • { hostname: string } - Matches against the hostname only
callback
function
required
Called with:
  • url - The current URL as a string
  • tab_id - The tab identifier

Examples

Match by hostname:
glide.autocmds.create('UrlEnter', { hostname: 'github.com' }, ({ url, tab_id }) => {
  console.log('Entered GitHub:', url);
  // Apply GitHub-specific configuration
  glide.buf.keymaps.set('normal', '<leader>gp', () => {
    // GitHub-specific action
  });
});
Match by regex:
glide.autocmds.create('UrlEnter', /youtube\.com\/watch/, ({ url }) => {
  console.log('Watching YouTube video:', url);
});

glide.autocmds.create('UrlEnter', /^https:\/\/.*\.pdf$/, ({ url }) => {
  console.log('Opened PDF:', url);
});
Implementation:
type AutocmdPatterns = {
  UrlEnter: RegExp | { hostname?: string };
  // ...

ModeChanged

Triggered whenever the mode changes.

Signature

glide.autocmds.create(
  'ModeChanged',
  pattern: "*" | `${GlideMode | "*"}:${GlideMode | "*"}`,
  callback: (args: { old_mode: GlideMode | null; new_mode: GlideMode }) => void
): void

Parameters

pattern
string
required
Pattern format: "old_mode:new_mode"Use * as a wildcard to match any mode:
  • "*:visual" - Entering visual mode from any mode
  • "visual:*" - Leaving visual mode to any mode
  • "visual:insert" - Specifically visual → insert
  • "*" - Any mode change
callback
function
required
Called with:
  • old_mode - Previous mode (may be null on initial load or config reload)
  • new_mode - New mode

Examples

Detect entering visual mode:
glide.autocmds.create('ModeChanged', '*:visual', ({ old_mode, new_mode }) => {
  console.log(`Entered visual mode from ${old_mode}`);
});
Detect leaving insert mode:
glide.autocmds.create('ModeChanged', 'insert:*', ({ new_mode }) => {
  console.log(`Left insert mode, now in ${new_mode}`);
});
Detect specific transition:
glide.autocmds.create('ModeChanged', 'visual:normal', () => {
  console.log('Returned to normal mode from visual');
});
Track all mode changes:
glide.autocmds.create('ModeChanged', '*', ({ old_mode, new_mode }) => {
  console.log(`Mode: ${old_mode}${new_mode}`);
});
Implementation:
ModeChanged: "*" | `${GlideMode | "*"}:${GlideMode | "*"}`;

KeyStateChanged

Triggered when the key sequence state changes.

Signature

glide.autocmds.create(
  'KeyStateChanged',
  callback: (args: {
    mode: GlideMode;
    sequence: string[];
    partial: boolean;
  }) => void
): void

Parameters

callback
function
required
Called with:
  • mode - Current mode
  • sequence - Current key sequence (e.g., ["g", "t"])
  • partial - Whether this is a partial sequence waiting for more keys

Triggered When

  1. A key is pressed that matches a key mapping
  2. A key is pressed that is part of a key mapping
  3. A key is pressed that cancels a previous partial key mapping
  4. A partial key mapping times out (see glide.o.mapping_timeout)

Example

With glide.keymaps.set('normal', 'gt', '...') defined:
  • Pressing g triggers: { sequence: ["g"], partial: true }
  • Then pressing t triggers: { sequence: ["g", "t"], partial: false }
  • Or pressing any other key triggers: { sequence: [], partial: false }
Display key sequence:
glide.autocmds.create('KeyStateChanged', ({ sequence, partial }) => {
  if (partial) {
    console.log('Waiting for key:', sequence.join(''));
  } else if (sequence.length > 0) {
    console.log('Executed:', sequence.join(''));
  }
});
Implementation:
KeyStateChanged: {
  readonly mode: GlideMode;
  readonly sequence: string[];
  readonly partial: boolean;
};

ConfigLoaded

Triggered when the config is loaded (initial load and every reload).

Signature

glide.autocmds.create(
  'ConfigLoaded',
  callback: () => void
): void

Example

glide.autocmds.create('ConfigLoaded', () => {
  console.log('Config loaded at:', new Date().toISOString());
  console.log('Current mode:', glide.ctx.mode);
});
Implementation:
ConfigLoaded: null;

WindowLoaded

Triggered when the window is initially loaded. Note: This is NOT invoked when the config is reloaded.

Signature

glide.autocmds.create(
  'WindowLoaded',
  callback: () => void
): void

Example

glide.autocmds.create('WindowLoaded', () => {
  console.log('Window initialized');
  // Perform one-time setup
});
Implementation:
WindowLoaded: null;

CommandLineExit

Triggered when the commandline UI is closed.

Signature

glide.autocmds.create(
  'CommandLineExit',
  callback: () => void
): void

Example

glide.autocmds.create('CommandLineExit', () => {
  console.log('Commandline closed');
});
Implementation:
CommandLineExit: null;

remove()

Remove a previously created autocmd.
glide.autocmds.remove<Event extends AutocmdEvent>(
  event: Event,
  callback: (args: AutocmdArgs[Event]) => void
): boolean

Parameters

event
AutocmdEvent
required
The event type to remove the callback from.
callback
function
required
The specific callback function to remove (must be the same reference).

Returns

true if the autocmd was found and removed, false otherwise.

Example

Create and remove autocmd:
function handleUrlChange({ url }: { url: string }) {
  console.log('URL changed:', url);
}

glide.autocmds.create('UrlEnter', /.*/, handleUrlChange);

// Later...
const removed = glide.autocmds.remove('UrlEnter', handleUrlChange);
console.log('Removed:', removed); // true
One-time autocmd:
glide.autocmds.create('UrlEnter', /example\.com/, function handleExample({ url }) {
  console.log('First visit to example.com:', url);
  // Remove itself after first trigger
  glide.autocmds.remove('UrlEnter', handleExample);
});
Implementation:
remove<Event extends glide.AutocmdEvent>(event: Event, cb?: (args: glide.AutocmdArgs[Event]) => void) {
  const events = GlideBrowser.autocmds[event];
  if (events == null) {
    return false;
  }

  const filtered = events.filter(({ callback }) => callback !== cb);
  GlideBrowser.autocmds[event] = filtered as (typeof GlideBrowser.autocmds)[Event];

  return filtered.length !== events.length;
}

Event Types Summary

type AutocmdEvent =
  | "UrlEnter"
  | "ModeChanged"
  | "ConfigLoaded"
  | "WindowLoaded"
  | "CommandLineExit"
  | "KeyStateChanged";

type AutocmdPatterns = {
  UrlEnter: RegExp | { hostname?: string };
  ModeChanged: "*" | `${GlideMode | "*"}:${GlideMode | "*"}`;
  ConfigLoaded: null;
  WindowLoaded: null;
  CommandLineExit: null;
  KeyStateChanged: null;
};

type AutocmdArgs = {
  UrlEnter: { readonly url: string; readonly tab_id: number };
  ModeChanged: {
    readonly old_mode: GlideMode | null;
    readonly new_mode: GlideMode;
  };
  ConfigLoaded: {};
  WindowLoaded: {};
  CommandLineExit: {};
  KeyStateChanged: {
    readonly mode: GlideMode;
    readonly sequence: string[];
    readonly partial: boolean;
  };
};

Complete Example

// Site-specific configurations
glide.autocmds.create('UrlEnter', { hostname: 'github.com' }, ({ url }) => {
  console.log('GitHub:', url);
  glide.bo.hint_size = "14px";
  glide.buf.keymaps.set('normal', '<leader>pr', () => {
    // Navigate to pull requests
    const base = new URL(url).origin + new URL(url).pathname;
    window.location.href = base + '/pulls';
  });
});

glide.autocmds.create('UrlEnter', /youtube\.com/, ({ url }) => {
  console.log('YouTube:', url);
  // Hide YouTube recommendations
  glide.styles.add(css`
    ytd-watch-next-secondary-results-renderer {
      display: none !important;
    }
  `, { id: 'hide-yt-recommendations' });
});

// Mode-based behavior
glide.autocmds.create('ModeChanged', '*:insert', () => {
  console.log('Entered insert mode');
});

glide.autocmds.create('ModeChanged', 'insert:*', () => {
  console.log('Left insert mode');
});

// Track key sequences
glide.autocmds.create('KeyStateChanged', ({ sequence, partial }) => {
  if (partial && sequence.length > 0) {
    console.log('Partial sequence:', sequence.join(''));
  }
});

// Initialization
let configLoadCount = 0;
glide.autocmds.create('ConfigLoaded', () => {
  configLoadCount++;
  console.log(`Config loaded ${configLoadCount} time(s)`);
});

glide.autocmds.create('WindowLoaded', () => {
  console.log('Window loaded at:', new Date());
  console.log('OS:', glide.ctx.os);
  console.log('Version:', glide.ctx.version);
});

// Commandline tracking
glide.autocmds.create('CommandLineExit', () => {
  console.log('Commandline closed');
});

// Self-removing autocmd
glide.autocmds.create('UrlEnter', /first-time/, function firstVisit({ url }) {
  console.log('First visit to matching URL:', url);
  glide.autocmds.remove('UrlEnter', firstVisit);
});

Build docs developers (and LLMs) love