GitHunt
EW

ewilderj/emacs-copilot-sdk

Pure Emacs Lisp client for the GitHub Copilot SDK

  • copilot-sdk.el

By [[https://github.com/ewilderj][Edd Wilder-James]], co-authored with [[https://github.com/features/copilot][GitHub Copilot]].

Pure Emacs Lisp client for the [[https://githubnext.com/projects/copilot-sdk][GitHub Copilot SDK]].

Talks directly to the Copilot CLI over JSON-RPC 2.0 with Content-Length
framing — the same protocol [[https://github.com/joaotavora/eglot][eglot]] uses for LSP.

See [[https://github.com/ewilderj/emacs-copilot-sdk-examples][emacs-copilot-sdk-examples]] for working applications built on this SDK:
echo-bot, docstring generator, AI commit messages, and an org-mode inbox processor.

** Requirements

  • Emacs 29.1+
  • =jsonrpc= 1.0.25+ (built-in since Emacs 27)
  • The =copilot= CLI binary (from the Copilot SDK)
  • A valid GitHub Copilot authentication token (=GH_TOKEN= env var or
    pre-authenticated via =copilot auth=)

** Installation

*** From MELPA (planned)

#+begin_src elisp
(use-package copilot-sdk)
#+end_src

*** Manual

#+begin_src bash
git clone https://github.com/ewilderj/emacs-copilot-sdk
#+end_src

Add to your =load-path=:

#+begin_src elisp
(add-to-list 'load-path "/path/to/emacs-copilot-sdk")
(require 'copilot-sdk)
#+end_src

** Quick Start

#+begin_src elisp
;; Start the CLI connection
(copilot-sdk-start)

;; Define a tool the model can call
(copilot-sdk-define-tool
"get_time" "Get the current time."
(lambda (_args)
(copilot-sdk-tool-success (current-time-string))))

;; Create a session
(setq my-session
(copilot-sdk-create-session
:model "claude-sonnet-4-5"
:tools (copilot-sdk-tool-defs)
:system-message "You are a helpful assistant."))

;; Send a message (async — callbacks fire as events arrive)
(copilot-sdk-send my-session "What time is it?"
:on-message (lambda (text) (message "Response: %s" text))
:on-idle (lambda () (message "Done.")))

;; Or send and block until response
(copilot-sdk-send-and-wait my-session "What time is it?")
#+end_src

** API Overview

*** Connection

| Function | Description |
|--------------------------------+--------------------------------|
| =copilot-sdk-start= | Start the CLI subprocess |
| =copilot-sdk-stop= | Stop the CLI subprocess |
| =copilot-sdk-connected-p= | Check if connected |
| =copilot-sdk-ensure-connected= | Start if not already connected |

*** Sessions

| Function | Description |
|--------------------------------+--------------------------------|
| =copilot-sdk-create-session= | Create a new session |
| =copilot-sdk-resume-session= | Resume an existing session |
| =copilot-sdk-destroy-session= | Destroy a session |
| =copilot-sdk-delete-session= | Permanently delete a session |
| =copilot-sdk-list-sessions= | List all sessions |

*** Messaging

| Function | Description |
|-----------------------------+-------------------------------------|
| =copilot-sdk-send= | Send message (async with callbacks) |
| =copilot-sdk-send-and-wait= | Send message and block for response |

*** Tools

| Function | Description |
|---------------------------+------------------------------------|
| =copilot-sdk-define-tool= | Register a tool the model can call |
| =copilot-sdk-tool-defs= | Get tool definitions (for sessions)|
| =copilot-sdk-clear-tools= | Remove all tools |

*** Handlers

| Function | Description |
|--------------------------------------+-----------------------------|
| =copilot-sdk-set-permission-handler= | Handle permission requests |
| =copilot-sdk-set-user-input-handler= | Handle user input requests |
| =copilot-sdk-on= | Subscribe to session events |

*** Queries

| Function | Description |
|--------------------------+--------------------------|
| =copilot-sdk-ping= | Ping the CLI |
| =copilot-sdk-status= | Get CLI version info |
| =copilot-sdk-auth-status= | Check authentication |
| =copilot-sdk-list-models= | List available models |

** Configuration

| Variable | Default | Description |
|---------------------------+-------------+------------------------|
| =copilot-sdk-cli-path= | ="copilot"= | Path to the CLI binary |
| =copilot-sdk-log-level= | ="info"= | CLI log level |

Set =COPILOT_CLI_PATH= environment variable to override the CLI path.

** Architecture

This package is a thin client — it manages the CLI subprocess and
dispatches JSON-RPC messages. It is intentionally unopinionated about
UI. Build your Emacs assistant on top of this.

#+begin_example
┌──────────────────────────────────────┐
│ Your Application (e.g. emacs-copilot)│
├──────────────────────────────────────┤
│ copilot-sdk.el │
│ jsonrpc-process-connection │
├──────────────────────────────────────┤
│ copilot CLI (Node.js subprocess) │
│ JSON-RPC 2.0 / stdio │
├──────────────────────────────────────┤
│ GitHub Copilot API │
└──────────────────────────────────────┘
#+end_example

** Running Tests

#+begin_src bash
emacs --batch -L . -l test-copilot-sdk.el -f ert-run-tests-batch-and-exit
#+end_src

** License

GPL-3.0-or-later. See [[file:LICENSE][LICENSE]].

Languages

Emacs Lisp100.0%

Contributors

GNU General Public License v3.0
Created February 16, 2026
Updated March 5, 2026
ewilderj/emacs-copilot-sdk | GitHunt