# How to Create Custom Context Providers for Continue: A Complete Implementation Guide

> Learn to create custom context providers for Continue by implementing IContextProvider and registering it. Enhance your Continue IDE experience with this comprehensive guide.

- Repository: [Continue/continue](https://github.com/continuedev/continue)
- Tags: how-to-guide
- Published: 2026-06-24

---

**You can create custom context providers for Continue by implementing the `IContextProvider` interface with a `description` property and `getContextItems` method, then registering your provider via `registerCustomContextProvider` in the VS Code extension or through your [`config.json`](https://github.com/continuedev/continue/blob/main/config.json) file.**

Continue is an open-source AI coding assistant that lets you augment LLM prompts with context items fetched from any data source. Creating custom context providers allows you to integrate internal documentation, proprietary APIs, or specialized knowledge bases directly into your AI workflow using the `@` mention syntax.

## Understanding the IContextProvider Interface

Every custom context provider must implement the `IContextProvider` interface defined in [[`core/index.d.ts`](https://github.com/continuedev/continue/blob/main/core/index.d.ts)](https://github.com/continuedev/continue/blob/main/core/index.d.ts). This contract ensures that Continue can uniformly discover, display, and execute your provider across the VS Code extension and GUI.

The interface requires two core members:

- **`description`**: A `ContextProviderDescription` object containing metadata such as `title` (displayed in the dropdown), `type` (one of `"normal"`, `"query"`, or `"submenu"`), and optional `extras` for UI hints like icons or placeholders.
- **`getContextItems(query)`**: An async method that receives the user's query string and returns a `Promise<GetContextItem[]>` containing the snippets to inject into the prompt.

## Implementing Your First Custom Context Provider

### Step 1: Create the Provider Class

Create a new TypeScript file for your provider. In this example, we build a provider that fetches data from an external REST API.

```typescript
// src/context/providers/MyProvider.ts
import { IContextProvider, ContextProviderDescription, GetContextItem } from "core";

export class MyProvider implements IContextProvider {
  get description(): ContextProviderDescription {
    return {
      title: "MyProvider",
      type: "normal",
      extras: {
        placeholder: "Enter search term...",
        icon: "search",
      },
    };
  }

  async getContextItems(query: string): Promise<GetContextItem[]> {
    const response = await fetch(
      `https://my.api/lookup?q=${encodeURIComponent(query)}`
    );
    const data = await response.json();

    return data.results.map((r: any) => ({
      title: r.title,
      id: r.id,
      content: r.snippet,
      metadata: { source: "my-api" },
    }));
  }
}

```

### Step 2: Configure the Provider Description

The `description` object controls how your provider appears in the Continue UI. The `title` field becomes the `@` command users type (e.g., `@MyProvider`). Available types are:

- **`normal`**: Standard query-based providers.
- **`query`**: Providers that handle structured query parsing.
- **`submenu`**: Providers that display nested selection options.

Optional `extras` include `placeholder` text for the input field and `icon` for visual identification.

## Registering Custom Context Providers

Once implemented, you must register your provider with the Continue runtime. Choose the method that fits your deployment scenario.

### Method A: Programmatic Registration in VS Code

For VS Code extension development, import your provider and call `registerCustomContextProvider` inside the extension activation routine in [[`extensions/vscode/src/extension/VsCodeExtension.ts`](https://github.com/continuedev/continue/blob/main/extensions/vscode/src/extension/VsCodeExtension.ts)](https://github.com/continuedev/continue/blob/main/extensions/vscode/src/extension/VsCodeExtension.ts):

```typescript
import { MyProvider } from "./src/context/providers/MyProvider";

export function activate(context: vscode.ExtensionContext) {
  const extension = new VsCodeExtension();
  extension.registerCustomContextProvider(new MyProvider());
}

```

This stores the provider in the runtime configuration, making it available across sessions.

### Method B: Configuration via config.json

For CLI or SDK usage, declare your provider in [`config.json`](https://github.com/continuedev/continue/blob/main/config.json). The `ConfigHandler` will dynamically import the module at runtime:

```json
{
  "customContextProviders": [
    {
      "module": "./src/context/providers/MyProvider.ts",
      "className": "MyProvider"
    }
  ]
}

```

After registration, reload the extension or restart Continue. Your provider now appears in the `@` dropdown and can be invoked with syntax like `@MyProvider <query>`.

## Complete Example: GitHub Issues Integration

Here is a production-ready example that integrates GitHub Issues into your Continue workflow.

```typescript
// src/context/providers/GithubIssuesProvider.ts
import { IContextProvider, ContextProviderDescription, GetContextItem } from "core";

export class GithubIssuesProvider implements IContextProvider {
  get description(): ContextProviderDescription {
    return {
      title: "GitHub Issues",
      type: "normal",
      extras: {
        placeholder: "repo:owner/name <search term>",
        icon: "github",
      },
    };
  }

  async getContextItems(query: string): Promise<GetContextItem[]> {
    const [repo, term] = query.split(" ", 2);
    const url = `https://api.github.com/search/issues?q=${encodeURIComponent(term)}+repo:${repo}`;
    const res = await fetch(url, {
      headers: { Accept: "application/vnd.github+json" },
    });
    const json = await res.json();

    return json.items.map((issue: any) => ({
      title: `#${issue.number}: ${issue.title}`,
      id: issue.id,
      content: issue.body ?? "",
      metadata: { url: issue.html_url, state: issue.state },
    }));
  }
}

```

**Usage in the editor:**

```

@GitHub Issues repo:facebook/react button component

```

The provider returns matching issues, and Continue embeds the issue bodies into the prompt sent to the LLM.

## Architecture and Lifecycle

Understanding the execution flow helps debug complex providers. When a user types `@ProviderName query`, the following occurs:

1. **Parsing**: The TipTap editor in [[`gui/src/components/mainInput/TipTapEditor/utils/renderPromptv1.ts`](https://github.com/continuedev/continue/blob/main/gui/src/components/mainInput/TipTapEditor/utils/renderPromptv1.ts)](https://github.com/continuedev/continue/blob/main/gui/src/components/mainInput/TipTapEditor/utils/renderPromptv1.ts) parses the `@` mention and extracts the provider name and query string.
2. **Resolution**: The system looks up the matching `ContextProviderDescription` in the registry, which includes both default providers and custom ones registered via `registerCustomContextProvider`.
3. **Execution**: The provider's `getContextItems` method is called with the query string.
4. **Request Building**: The returned `GetContextItem` objects are merged into the `GetContextRequest[]` payload.
5. **Streaming**: [[`gui/src/redux/thunks/streamResponse.ts`](https://github.com/continuedev/continue/blob/main/gui/src/redux/thunks/streamResponse.ts)](https://github.com/continuedev/continue/blob/main/gui/src/redux/thunks/streamResponse.ts) sends the final payload to the language model, including your custom context items.

## Summary

- **Implement `IContextProvider`**: Create a class with `description` metadata and an async `getContextItems` method defined in [`core/index.d.ts`](https://github.com/continuedev/continue/blob/main/core/index.d.ts).
- **Register your provider**: Use `registerCustomContextProvider` in [`extensions/vscode/src/extension/VsCodeExtension.ts`](https://github.com/continuedev/continue/blob/main/extensions/vscode/src/extension/VsCodeExtension.ts) for VS Code, or declare it in [`config.json`](https://github.com/continuedev/continue/blob/main/config.json) for CLI/SDK usage.
- **Leverage async operations**: Fetch data from REST APIs, databases, or local file systems within `getContextItems`.
- **Debug with metadata**: Include optional metadata in returned items to trace context sources in complex workflows.
- **Invoke with @ syntax**: Users trigger your provider by typing `@YourProviderName <query>` in the chat input.

## Frequently Asked Questions

### What TypeScript types do I need to import for a custom context provider?

Import `IContextProvider`, `ContextProviderDescription`, and `GetContextItem` from the `core` package. These types are defined in [`core/index.d.ts`](https://github.com/continuedev/continue/blob/main/core/index.d.ts) and ensure your provider conforms to the expected contract for title display and item retrieval.

### Can I access external APIs or databases from my context provider?

Yes. The `getContextItems` method is async, allowing you to fetch data from REST APIs, query databases, or read local files before returning the results. Simply return an array of objects matching the `GetContextItem` structure with `title`, `id`, `content`, and optional `metadata`.

### How do I debug issues with my custom context provider?

Include diagnostic information in the `metadata` field of your returned context items. You can also trace the provider execution flow through [`gui/src/components/mainInput/TipTapEditor/utils/renderPromptv1.ts`](https://github.com/continuedev/continue/blob/main/gui/src/components/mainInput/TipTapEditor/utils/renderPromptv1.ts), where the system resolves `@` mentions and builds the prompt payload that gets sent to the LLM.

### What is the difference between "normal", "query", and "submenu" provider types?

The `type` field in `ContextProviderDescription` controls UI behavior. `"normal"` providers accept direct text queries, `"query"` providers may implement specialized parsing for structured search syntax, and `"submenu"` providers display nested selection interfaces rather than immediate text input. Choose based on how users should interact with your data source.