# How to Create Custom Search Engine Plugins for wigolo

> Learn how to create custom search engine plugins for wigolo. Implement a Node module, follow the SearchEngine interface, and install it with the wigolo CLI.

- Repository: [Towhid Khan/wigolo](https://github.com/KnockOutEZ/wigolo)
- Tags: how-to-guide
- Published: 2026-07-29

---

**Developers create custom search engine plugins for wigolo by implementing a Node module that exports a `searchEngine` object conforming to the `SearchEngine` interface defined in [`src/types.ts`](https://github.com/KnockOutEZ/wigolo/blob/main/src/types.ts), placing it in the `~/.wigolo/plugins` directory, and installing it via the `wigolo plugin add` CLI command.**

The wigolo open-source project provides a modular search architecture that allows developers to extend its capabilities through custom plugins. By implementing the standard plugin interface, you can integrate proprietary indexes, third-party APIs, or specialized search backends into wigolo's multi-engine dispatch pipeline. This guide walks through the complete process of creating, validating, and deploying custom search engine plugins for wigolo based on the actual source implementation.

## Understanding the Plugin Architecture

wigolo loads plugins from `~/.wigolo/plugins` (or the directory specified by the `WIGOLO_PLUGINS_DIR` environment variable). According to the source code in [`src/plugins/loader.ts`](https://github.com/KnockOutEZ/wigolo/blob/main/src/plugins/loader.ts), the system treats each plugin as a standard Node module that must export a `searchEngine` object. This object is validated against the `SearchEngine` interface defined in [`src/types.ts`](https://github.com/KnockOutEZ/wigolo/blob/main/src/types.ts) lines 14-18.

Once validated, the plugin registers with the `PluginRegistry` ([`src/plugins/registry.ts`](https://github.com/KnockOutEZ/wigolo/blob/main/src/plugins/registry.ts) lines 22-27) and becomes available for multi-engine dispatch. The architecture ensures that custom engines participate fully in result fusion, deduplication, and on-device reranking alongside built-in engines.

## Step-by-Step Implementation Guide

### Create the Plugin Directory Structure

Create a new directory for your plugin with a standard Node.js project structure. At minimum, you need a [`package.json`](https://github.com/KnockOutEZ/wigolo/blob/main/package.json) file with a `main` field pointing to your entry file (commonly `index.mjs`).

```json
{
  "name": "my-wigolo-search",
  "version": "0.1.0",
  "main": "index.mjs"
}

```

### Implement the SearchEngine Interface

Create an `index.mjs` file that exports a `searchEngine` object with two required properties: a unique `name` string and an async `search(query, options?)` method. The `search` method must return an array of objects conforming to the `RawSearchResult` type defined in [`src/types.ts`](https://github.com/KnockOutEZ/wigolo/blob/main/src/types.ts) lines 70-78.

The `RawSearchResult` interface requires:
- `title`: string
- `url`: string  
- `snippet`: string
- `relevance_score`: number (0-1 float)
- `engine`: string (typically matching your engine name)

```javascript
export const searchEngine = {
  name: 'my-search-engine',
  
  async search(query) {
    // Replace with your actual API call or index query
    const response = await fetch(`https://api.example.com/search?q=${encodeURIComponent(query)}`);
    const data = await response.json();
    
    // Map to wigolo's expected shape
    return data.results.map(r => ({
      title: r.title,
      url: r.url,
      snippet: r.description,
      relevance_score: r.score,
      engine: 'my-search-engine',
    }));
  },
};

```

### Handle Optional Dependencies

If your plugin requires external libraries, install them within the plugin directory. wigolo loads plugins as isolated modules, so dependencies must be resolvable from the plugin's location.

## Installing and Validating Your Plugin

Use the wigolo CLI to install your plugin from a local path or Git repository:

```bash
wigolo plugin add /path/to/my-search-engine

```

```bash
wigolo plugin add https://github.com/user/my-search-engine.git

```

The CLI command (handled by the loader logic in [`src/plugins/loader.ts`](https://github.com/KnockOutEZ/wigolo/blob/main/src/plugins/loader.ts) around lines 31-46) clones the repository into the plugins folder and performs initial validation. To explicitly verify that your implementation conforms to the required contracts, run:

```bash
wigolo plugin validate

```

This validates that the exported `searchEngine` object matches the interface requirements and reports any structural errors before runtime.

## Using the Custom Engine in Production

Once loaded, your custom engine appears in telemetry alongside built-in engines. To invoke it explicitly, include the engine name in the `search_engines` field of your `SearchInput` payload:

```javascript
await fetch('http://localhost:8080/v1/search', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    query: 'open-source licensing',
    search_engines: ['my-search-engine'],
  }),
});

```

The engine participates in the standard result processing pipeline, including deduplication and relevance scoring, exactly as implemented for core engines in the main codebase.

## Summary

- Custom search engine plugins for wigolo are Node modules stored in `~/.wigolo/plugins` (or `WIGOLO_PLUGINS_DIR`) that export a `searchEngine` object.
- The implementation must conform to the `SearchEngine` interface defined in [`src/types.ts`](https://github.com/KnockOutEZ/wigolo/blob/main/src/types.ts) (lines 14-18) and return `RawSearchResult` objects (lines 70-78).
- Install plugins using `wigolo plugin add` and validate them with `wigolo plugin validate` to ensure contract compliance.
- Custom engines integrate fully with wigolo's multi-engine dispatch, participating in result fusion and reranking just like built-in engines.

## Frequently Asked Questions

### What interface methods must a custom search engine plugin implement?

A custom search engine plugin must export a `searchEngine` object containing a `name` property and an async `search(query, options?)` method. The `search` method must return a Promise that resolves to an array of `RawSearchResult` objects. According to [`src/types.ts`](https://github.com/KnockOutEZ/wigolo/blob/main/src/types.ts), each result must include `title`, `url`, `snippet`, `relevance_score` (a float between 0 and 1), and `engine` properties.

### Where does wigolo load plugins from?

By default, wigolo loads plugins from the `~/.wigolo/plugins` directory. You can override this location by setting the `WIGOLO_PLUGINS_DIR` environment variable. The loader logic in [`src/plugins/loader.ts`](https://github.com/KnockOutEZ/wigolo/blob/main/src/plugins/loader.ts) scans this directory, imports each module, validates the exported objects, and registers valid engines with the `PluginRegistry`.

### How do I debug a plugin that fails validation?

Run `wigolo plugin validate` to check for interface mismatches or missing required properties. Ensure your [`package.json`](https://github.com/KnockOutEZ/wigolo/blob/main/package.json) has a valid `main` entry pointing to your implementation file, and verify that your `searchEngine` export includes both the `name` string and `search` function. Check that returned results match the `RawSearchResult` shape defined in [`src/types.ts`](https://github.com/KnockOutEZ/wigolo/blob/main/src/types.ts) lines 70-78, particularly ensuring `relevance_score` is a number between 0 and 1.

### Can custom search engines work alongside built-in engines?

Yes. When you don't specify `search_engines` explicitly in your search request, wigolo's multi-engine dispatch automatically includes all valid registered engines, both built-in and custom, in the search process. Custom engines participate fully in result fusion, deduplication, and the reranking pipeline defined in the core architecture.