Extensions and Addons
Glide provides a programmatic API for installing and managing Firefox extensions (addons) directly from your config file.
Installation
Install from URL
Install extensions from Mozilla Addons (AMO) or any XPI URL:
glide.autocmds.create("ConfigLoaded", async () => {
await glide.addons.install(
"https://addons.mozilla.org/firefox/downloads/file/..."
);
});
Get XPI URL
To find an extension’s XPI URL:
- Visit the extension page on addons.mozilla.org
- Right-click “Add to Firefox”
- Select “Copy Link”
Installation Behavior
By default, glide.addons.install() only installs if the addon isn’t already present:
const result = await glide.addons.install(xpi_url);
console.log(result.cached); // true if already installed
Force Reinstall
Reinstall even if already present:
const result = await glide.addons.install(xpi_url, { force: true });
console.log(result.cached); // always false
Installation Options
interface AddonInstallOptions {
/** Force reinstall even if addon is already installed */
force?: boolean;
/** Allow the extension to run in private browsing windows */
private_browsing_allowed?: boolean;
}
Example:
await glide.addons.install(xpi_url, {
force: true,
private_browsing_allowed: true
});
Managing Addons
List Installed Addons
Get all installed addons:
const addons = await glide.addons.list();
for (const addon of addons) {
console.log(`${addon.name} (${addon.id})`);
console.log(` Type: ${addon.type}`);
console.log(` Active: ${addon.active}`);
}
Filter by Type
Filter addons by type:
// Get only extensions
const extensions = await glide.addons.list("extension");
// Get multiple types
const items = await glide.addons.list(["extension", "locale", "dictionary"]);
Available types:
"extension"
"locale"
"dictionary"
"theme"
Addon Object
The addon object provides:
interface Addon {
id: string; // Extension ID
name: string; // Display name
type: AddonType; // "extension", "theme", etc.
active: boolean; // Whether addon is enabled
// Methods
uninstall(): Promise<void>;
reload(): Promise<void>;
}
Uninstall Addon
glide.keymaps.set("normal", "<leader>xu", async () => {
const addons = await glide.addons.list("extension");
const ublock = addons.find(a => a.name.includes("uBlock"));
if (ublock) {
await ublock.uninstall();
console.log("Uninstalled uBlock Origin");
}
});
Reload Addon
Restart an extension (useful for development):
const addon = await glide.addons.install(xpi_url);
await addon.reload();
Practical Examples
Essential Extensions
Install a curated set of extensions:
const EXTENSIONS = [
{
name: "uBlock Origin",
url: "https://addons.mozilla.org/firefox/downloads/file/..."
},
{
name: "Bitwarden",
url: "https://addons.mozilla.org/firefox/downloads/file/...",
private_browsing: true
}
];
glide.autocmds.create("ConfigLoaded", async () => {
for (const ext of EXTENSIONS) {
try {
const result = await glide.addons.install(ext.url, {
private_browsing_allowed: ext.private_browsing ?? false
});
if (!result.cached) {
console.log(`Installed ${ext.name}`);
}
} catch (err) {
console.error(`Failed to install ${ext.name}:`, err);
}
}
});
Conditional Installation
Install extensions based on conditions:
glide.autocmds.create("ConfigLoaded", async () => {
// Only install dev tools on localhost
if (glide.ctx.os === "linux") {
await glide.addons.install(
"https://addons.mozilla.org/firefox/downloads/file/..."
);
}
});
Check Installation Status
glide.keymaps.set("normal", "<leader>xi", async () => {
const addons = await glide.addons.list("extension");
const names = addons.map(a => a.name).join("\n");
console.log("Installed extensions:\n" + names);
});
Development Workflow
Reload extension during development:
glide.keymaps.set("normal", "<leader>xr", async () => {
const addons = await glide.addons.list();
const dev_addon = addons.find(a => a.id === "my-extension@example.com");
if (dev_addon) {
await dev_addon.reload();
console.log("Extension reloaded");
}
});
Bulk Operations
glide.keymaps.set("normal", "<leader>xd", async () => {
const addons = await glide.addons.list("extension");
// Disable all extensions
for (const addon of addons) {
if (addon.active) {
await addon.disable?.();
}
}
});
WebExtension API Access
Glide provides access to the WebExtension browser API in your config:
glide.keymaps.set("normal", "<leader>td", async () => {
await browser.theme.update({
colors: { frame: "#1a1a1a" }
});
});
Differences from Standard API
-
All methods return Promises
// Standard WebExtension
browser.tabs.query({...}).then(...);
// Glide (same, but enforced)
await browser.tabs.query({...});
-
Some APIs not supported
browser.runtime.connect() and Port APIs
- Some chrome-specific extensions
Common WebExtension Operations
Theme Management
// Update theme
await browser.theme.update({
colors: {
frame: "#1a1a1a",
tab_background_text: "#ffffff",
toolbar: "#2d2d2d"
}
});
// Reset theme
await browser.theme.reset();
Bookmark Management
// Create bookmark
await browser.bookmarks.create({
title: "Example",
url: "https://example.com"
});
// Search bookmarks
const results = await browser.bookmarks.search("example");
Download Management
glide.keymaps.set("normal", "<leader>d", async () => {
await browser.downloads.download({
url: glide.ctx.url.href,
filename: "page.html"
});
});
Restrictions
The browser API has limitations similar to standard WebExtensions:
The API will not function on protected pages like about:config, about:addons, or addons.mozilla.org. This will be addressed in future versions.
Advanced Patterns
Addon State Persistence
declare global {
interface GlideGlobals {
addon_ids?: Set<string>;
}
}
glide.g.addon_ids = new Set();
glide.autocmds.create("ConfigLoaded", async () => {
const addons = await glide.addons.list();
for (const addon of addons) {
glide.g.addon_ids!.add(addon.id);
}
});
Version-Specific Extensions
glide.autocmds.create("ConfigLoaded", async () => {
const version = parseInt(glide.ctx.firefox_version.split(".")[0]);
if (version >= 130) {
// Install extensions that require Firefox 130+
await glide.addons.install("https://...");
}
});
Extension Health Check
glide.keymaps.set("normal", "<leader>xc", async () => {
const addons = await glide.addons.list("extension");
const inactive = addons.filter(a => !a.active);
if (inactive.length > 0) {
console.log("Inactive extensions:");
for (const addon of inactive) {
console.log(` - ${addon.name}`);
}
} else {
console.log("All extensions active");
}
});
Troubleshooting
Installation Fails
Ensure the XPI URL is valid and accessible:
try {
await glide.addons.install(xpi_url);
} catch (err) {
console.error("Installation failed:", err);
}
Verify Installation
const addons = await glide.addons.list();
const installed = addons.find(a => a.id === "addon-id@example.com");
if (installed) {
console.log(`${installed.name} is installed`);
}
See Also