How to Include the GitHub Copilot SDK in a Rust Project Using Cargo
Add the github-copilot-sdk crate to your Cargo.toml dependencies, optionally enabling the bundled-in-process feature for FFI runtime or disabling default features to use an external CLI binary.
The GitHub Copilot SDK provides a Rust crate that wraps the Copilot CLI via JSON-RPC, enabling programmatic access to GitHub's AI pair programming capabilities. To include the GitHub Copilot SDK in a Rust project using Cargo, you add the crate as a dependency and initialize the Client struct with your preferred transport configuration. This guide walks through the exact steps required to integrate the SDK according to the github/copilot-sdk source code, configure its feature flags, and establish your first client connection.
Adding the Dependency to Cargo.toml
The SDK is published to crates.io as github-copilot-sdk. The crate uses feature flags to control how the Copilot runtime is packaged and executed.
According to rust/Cargo.toml, the default feature set includes bundled-cli, which automatically packages the Copilot CLI binary inside your compiled application. You can modify this behavior depending on your deployment requirements.
Add the dependency to your Cargo.toml:
[dependencies]
# Default: includes the bundled CLI binary
github-copilot-sdk = "0.0.0-dev"
# Option A: Enable in-process FFI runtime instead of CLI spawning
github-copilot-sdk = { version = "0.0.0-dev", features = ["bundled-in-process"] }
# Option B: Disable bundling entirely to provide your own CLI binary
github-copilot-sdk = { version = "0.0.0-dev", default-features = false }
Available features defined in rust/Cargo.toml include:
bundled-cli(default): Embeds the Copilot CLI binary and extracts it at runtimebundled-in-process: Links the Copilot runtime as an in-process FFI library instead of spawning a separate processderive: Enablesschemarssupport for JSON schema generation via derive macrostest-support: Exposes internal testing utilities and mock transports
Understanding the SDK Architecture
Before initializing the client, understand the core types defined in rust/src/lib.rs. These types handle the connection lifecycle, configuration, and communication protocol.
Client
The Client struct serves as the primary entry point. When you call Client::start(), the SDK resolves the transport method, spawns the CLI process (or connects to an existing one), and validates protocol compatibility. The client encapsulates the JSON-RPC connection and manages background tasks for message handling.
ClientOptions
ClientOptions provides a builder-pattern configuration struct. Located in rust/src/lib.rs, it allows you to specify:
- Transport mode (
Transport::Stdio,Tcp,External, orInProcess) - CLI binary location via
CliProgram - Authentication tokens forwarded via
COPILOT_SDK_AUTH_TOKEN - Logging levels for the Copilot runtime
- OpenTelemetry telemetry configuration
Transport
The Transport enum in rust/src/lib.rs defines four communication methods:
Stdio: Spawns the CLI as a subprocess and communicates over stdin/stdout pipes (default behavior)Tcp: Binds to a local TCP port for remote debugging or containerized deploymentsExternal: Connects to an already-running Copilot server instanceInProcess: Uses the FFI runtime whenbundled-in-processis enabled, eliminating subprocess overhead
Feature Flags and Binary Resolution
When using the default bundled-cli feature, the SDK uses logic in rust/src/resolve.rs to extract the appropriate platform-specific CLI binary from the crate's assets to a temporary location at runtime. If you disable default features and provide your own binary, the SDK skips this extraction step and uses the path specified in ClientOptions.
Initializing the SDK in Your Rust Code
Once the dependency is added, import the SDK and initialize a client. The following minimal example demonstrates starting a client with default options and creating a session:
use github_copilot_sdk::{Client, ClientOptions, LogLevel, Transport};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Configure client options using the builder pattern
let opts = ClientOptions::new()
.with_log_level(LogLevel::Info)
.with_transport(Transport::Stdio);
// Start the client: spawns CLI process and establishes JSON-RPC connection
let client = Client::start(opts).await?;
// Create a new conversation session
let session = client.create_session(Default::default()).await?;
// Send a message to the Copilot model
let response = session
.send_message("Explain Rust ownership and borrowing")
.await?;
println!("Response: {}", response.text);
Ok(())
}
Key implementation details from rust/src/session.rs:
create_session()returns aSessionhandle that manages conversation statesend_message()serializes the request to JSON-RPC, sends it to the CLI process, and deserializes the response- All async methods require a Tokio runtime
Advanced Configuration Examples
Using TCP Transport
For scenarios requiring network accessibility or container orchestration, configure the TCP transport as implemented in rust/src/lib.rs:
use github_copilot_sdk::{Client, ClientOptions, LogLevel, Transport};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let opts = ClientOptions::new()
.with_transport(Transport::Tcp {
port: 0, // 0 allows the OS to assign an available port
connection_token: None, // SDK auto-generates a secure token
})
.with_log_level(LogLevel::Debug)
.with_github_token("ghp_xxxxxxxxxxxx"); // Optional: forward GitHub token
let client = Client::start(opts).await?;
// Session handling remains identical to the stdio example
let session = client.create_session(Default::default()).await?;
let response = session.send_message("Refactor this code").await?;
Ok(())
}
Disabling Bundled Features for Custom CLI
If you distribute the Copilot CLI separately or need to comply with specific licensing requirements, disable bundling and provide the binary path:
// In Cargo.toml
[dependencies]
github-copilot-sdk = { version = "0.0.0-dev", default-features = false }
// In your code
let opts = ClientOptions::new()
.with_cli_program("/usr/local/bin/copilot-cli");
Summary
- Add
github-copilot-sdkto yourCargo.tomldependencies to include the GitHub Copilot SDK in your Rust project using Cargo. - The default
bundled-clifeature automatically packages the Copilot CLI; usedefault-features = falseto provide your own binary. - Enable the
bundled-in-processfeature for FFI-based in-process runtime instead of subprocess communication. - Core types (
Client,ClientOptions,Transport) are defined inrust/src/lib.rsand re-exported for public use. - Initialize the SDK with
Client::start(opts).await?after configuring options viaClientOptions::new(). - Session management and message handling are implemented in
rust/src/session.rsusing asynchronous JSON-RPC over your selected transport.
Frequently Asked Questions
What is the difference between the bundled-cli and bundled-in-process features?
The bundled-cli feature (enabled by default) packages the Copilot CLI as an external binary that the SDK spawns as a subprocess and communicates with via JSON-RPC over pipes or TCP. The bundled-in-process feature links the Copilot runtime directly into your application as a shared library using FFI, eliminating the subprocess overhead and allowing tighter integration. You can enable both features simultaneously, but typically you choose one based on whether you prefer process isolation or lower latency.
How do I provide my own Copilot CLI binary instead of using the bundled one?
Set default-features = false in your Cargo.toml dependency declaration to disable the automatic bundling. Then, when constructing your client in Rust, use ClientOptions::new().with_cli_program("/path/to/copilot-cli") to specify the exact location of your custom binary. The SDK will skip the extraction logic in rust/src/resolve.rs and spawn your provided executable instead.
What transport options does the SDK support for communicating with the Copilot runtime?
As defined in rust/src/lib.rs, the SDK supports four transport variants: Stdio (default, uses stdin/stdout pipes), Tcp (binds to a TCP socket for remote connections), External (connects to an already-running server), and InProcess (uses FFI when the bundled-in-process feature is enabled). Each variant implements the same Transport trait, allowing you to switch communication methods without changing your session handling code.
Where are the core SDK types like Client and ClientOptions defined?
All public SDK types are defined in rust/src/lib.rs and re-exported at the crate root. This includes Client (the main entry point), ClientOptions (configuration builder), Transport (communication protocol selector), and Session (conversation management). Internal implementation details for binary resolution reside in rust/src/resolve.rs, while JSON-RPC protocol handling is implemented in rust/src/rpc.rs.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →