Creating a GitHub Copilot Extension: A Step-by-Step Guide

Nick TaylorNick Taylor
8 min read

GitHub Copilot, the AI-powered coding assistant, has recently introduced Copilot Extensions to enhance its ecosystem. This feature, now in public beta, allows developers to create custom extensions that integrate with Copilot. In this blog post, we'll walk through the process of creating your first GitHub Copilot extension.

Before we begin, it's important to note that you need to have an active GitHub Copilot subscription to create and use Copilot extensions.

Creating the Endpoint for Your Copilot Extension

A Copilot extension is essentially a GitHub app with a specific endpoint. Let's set up the project and create this endpoint, which together will form your Copilot extension.

Setting Up Your Project

In this guide, we're using Hono.js as our web framework, but you can use any web framework or web server of your choice. The core concepts will remain the same regardless of the framework you choose. The only thing to be aware of about the SDK is, for the moment, the only languages supported are TypeScript and JavaScript.

  1. Create a new Hono project using the Hono CLI:

     npm create hono@latest
    

    Follow the prompts to set up your project. This will create a new TypeScript project using Hono.js, a lightweight and fast web framework.

  2. Install the preview SDK for Copilot extensions and Octokit's core package:

     npm install @copilot-extensions/preview-sdk @octokit/core
    

    %[https://github.com/copilot-extensions/preview-sdk.js]

  3. Open your main file (e.g., src/index.ts) and let's start by importing the necessary dependencies:

     import { Hono } from 'hono'
     import { Octokit } from "@octokit/core";
     import {
       createAckEvent,
       createDoneEvent,
       createErrorsEvent,
       createTextEvent,
       getUserMessage,
       verifyAndParseRequest,
     } from "@copilot-extensions/preview-sdk";
    
     const app = new Hono();
    

Implementing the Endpoint

Now, let's implement the endpoint that will handle requests from GitHub Copilot:

  1. Create a root route that receives a form post, /. This is the endpoint that Copilot will interact with:

     app.post("/", async (c) => {
       // ... (we'll fill this in next)
     });
    
  2. When a message comes in, you need to verify the request and parse the payload:

     const body = await c.req.text();
     const signature = c.req.header("github-public-key-signature") ?? "";
     const keyID = c.req.header("github-public-key-identifier") ?? "";
    
     const { isValidRequest, payload } = await verifyAndParseRequest(
       body,
       signature,
       keyID,
       {
         token: tokenForUser,
       }
     );
    
     if (!isValidRequest) {
       console.error("Request verification failed");
       c.header("Content-Type", "text/plain");
       c.status(401);
       c.text("Request could not be verified");
       return;
     }
    
  3. After verifying the request, process the message and create a response. Here's a simple example that greets the user:

     const octokit = new Octokit({ auth: tokenForUser });
     const user = await octokit.request("GET /user");
     const prompt = getUserMessage(payload);
    
     return c.text(
       createAckEvent() +
         createTextEvent(
           `Welcome ${user.data.login}! It looks like you asked the following question, "${prompt}". This is a GitHub Copilot extension template, so it's up to you to decide what you want to implement to answer prompts.`
         ) +
         createDoneEvent()
     );
    

This example uses the GitHub Octokit package to get the user's login name and greets them. The createTextEvent function is used to create the response that GitHub Copilot will display.

Exposing Your Extension

To test your Copilot extension, you need to make it publicly accessible:

  1. If using Visual Studio Code (VS Code), enable port forwarding. Note that the port is private by default, a good thing, but for our use case, we need to set it to public.

    Port forwarding tab in the bottom dock of VS Code

  2. Alternatively, use tools like cloudflared or ngrok to expose a public URL.

In the provided code, the server is set up to run on port 3000:

const port = 3000;
console.log(`Server is running on port ${port}`);

serve({
  fetch: app.fetch,
  port,
});

It's worth mentioning that this setup is great for testing, but once you're ready to make your extension public, you'll need to deploy the web app (which acts as the GitHub app) to a publicly accessible location.

Creating a GitHub App

Create a new GitHub app on your personal account for testing purposes. Head to your settings page on GitHub, and at the bottom, to the left, click on the Developer Settings link. This will bring you to your GitHub apps. You can also directly navigate to your GitHub apps page at https://github.com/settings/apps.

General settings

  1. Enter a GitHub App name, e.g. my copilot extension

  2. Enter a URL for the homepage. This can be the same as the test URL for now.

  3. Set the Callback URL (currently required). This can be the same as the test URL for now. Even if you're not using OAuth you still need to put a URL here. I'm told in future this may no longer be required.

    A new GitHub app's settings page

  4. Disable webhooks if they're enabled.

    Webhooks settings section

  5. Make sure the app is initially accessible only to you. You can enable it for everyone when you're ready to make your GitHub Copilot extension publicly available.

    GitHub app visibility setting of just you or everyone

  6. Click the Create GitHub App button to create the GitHub app.

Permissions & events settings

Next up, we'll need to configure permissions. We want to provide the bare minimum permissions for a Copilot extension to work.

Permissions settings for a GitHub app

  1. Expand the Account permissions sections and set the Copilot Chat permission to read-only. The default is No access.

    Account permissions section of a GitHub app

  2. Click Save changes. Don't be alarmed by the Are you sure you want to update permissions? message.

    Save changes button

Copilot settings

  1. Set the App Type to Agent. It's set to Disabled by default.

  2. Set the URL to the root of the public URL you exposed via tunneling/port forwarding.

    A GitHub App's Copilot settings section

  3. Click Save.

Congratulations! You've configured your first Copilot extension!

GitHub apps section of developer settings on GitHub

Install Your Copilot Extension

Before we can use the extension, it has to be installed.

  1. Navigate to your GitHub apps in your developer settings.

    The GitHub apps section of GitHub developer settings

  2. Click the Edit button to edit the app.

  3. Go to the Install App section of the GitHub app's settings.

    GitHub App's Install App settings panel

  4. Click the Install button to install the application

  5. You're brought to an intermediary page to confirm the installation of the GitHub app. Click the Install button.

    GitHub app installation confirmation step

  6. Your Copilot extension is installed for your GitHub account.

    Post GitHub app installation screen showing the app installed

Testing Your Extension

You can test your Copilot extension in a few environments:

  1. GitHub.com's Copilot chat

  2. VS Code's Copilot Chat

  3. Visual Studio's Copilot Chat

For these environments, follow these steps:

  1. In the GitHub Copilot chat, type "@" to see available extensions.

  2. Your extension should appear as, e.g. "@my-copilot-extension".

    Copilot chat on GitHub.com displaying the available Copilot extensions

    Copilot chat in Visual Studio Code displaying the available Copilot extensions

  3. Select your extension and ask a question or perform an operation.

  4. The Copilot extension will return a response of Welcome your_github_username! It looks like you asked the following question, "your_question". This is a GitHub Copilot extension template, so it's up to you to decide what you want to implement to answer prompts.

    Copilot chat responding, "Welcome nickytonline! It looks like you asked the following question, "What is the most used programming language?". This is a GitHub Copilot extension template, so it's up to you to decide what you want to implement to answer prompts."

It won't respond to your specific question as that functionality has not been implemented. This is where you can explore the preview SDK or integrate with a third-party service to provide more meaningful responses.

A Real-World Example

I've created a proof-of-concept (POC) Copilot extension for OpenSauced, where I work, that demonstrates these principles in action.

This extension utilizes OpenSauced's StarSearch feature to provide open-source insights directly within Copilot.

Curious about StarSearch? ๐Ÿ‘‡

This POC showcases how you can leverage external APIs and services to create powerful, context-aware extensions that enhance the Copilot experience.

Grab the GitHub Copilot Extension Template

If you're interested in starting your own GitHub Copilot Extension, I've created a template to help you get started quickly:

This template provides a solid foundation for building your extension, incorporating best practices and a basic structure to build upon. The template uses the Hono.js Node.js server, but it's worth noting that Hono.js offers various adapters for different deployment environments. You can use adapters for platforms like Netlify, Vercel, Cloudflare Workers, and more. For more information on Hono.js and its adapters, check out their Getting Started guide.

I also encourage you to take a peek at the examples in the copilot-extensions organization on GitHub, including some examples in the preview SDK:

These examples can provide inspiration and guidance as you develop your own extensions.

Take a deep dive into Copilot extensions and the preview SDK

For a deeper dive into the preview SDK and Copilot extensions in general, check out this video: "Let's build a Copilot extension!" Shout out to Gregor Martynus (@gr2m) and Francis Batac (@francisfuzz) for hanging with me!

This video provides valuable insights into the development process and can help you understand the nuances of working with Copilot extensions.

I also encourage you to check out the official GitHub Copilot documentation.

Wrapping up

Creating a GitHub Copilot extension opens up new possibilities for enhancing your development workflow. By following this guide, you can start building custom extensions that leverage the power of Copilot while adding your own unique functionality.

Remember, the Copilot Extensions feature is still in beta, so keep an eye out for updates and improvements as the ecosystem evolves. This is an exciting time to get involved and potentially shape the future of AI-assisted coding!

Until the next one!

Other places you can find me:

๐Ÿ—ž๏ธ One Tip a Week Newsletter ๐ŸŽฌ YouTube ๐ŸŽฌ Twitch ๐ŸŽฌ nickyt.live ๐Ÿ’ป GitHub ๐Ÿ‘พ My Discord ๐Ÿฆ Twitter/X ๐Ÿงต Threads ๐ŸŒ My Website

4
Subscribe to my newsletter

Read articles from Nick Taylor directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Nick Taylor
Nick Taylor

Hello! My name is Nick Taylor. I'm a Senior Software Engineer at OpenSauced. I'm a fan of Open Source and have a growing interest in serverless and edge computing. I'm not a big fan of spiders, but I know they're doing good work eating bugs. I also stream on Twitch. I am a big fan of TypeScript, JavaScript, Node, and all things frontend. Aside from programming, I enjoy contributing to open source, hitting the gym, snowboarding, and rugby a long time ago.