# Local CLI setup Use a specific CLI binary instead of the SDK's bundled CLI. This is an advanced option—you supply the CLI path explicitly, and you are responsible for ensuring version compatibility with the SDK. **Use when:** You need to pin a specific CLI version, or work with the Go SDK (which does not bundle a CLI). ## How it works By default, the Node.js, Python, and .NET SDKs include their own CLI dependency (see [Default Setup](./bundled-cli.md)). If you need to override this—for example, to use a system-installed CLI—you can use the `Connection` option. ```mermaid flowchart LR subgraph YourMachine["Your Machine"] App["Your App"] --> SDK["SDK Client"] SDK -- "cliPath" --> CLI["Copilot CLI
(your own binary)"] CLI --> Keychain["🔐 System Keychain
(stored credentials)"] end CLI -- "API calls" --> Copilot["☁️ GitHub Copilot"] style YourMachine fill:#0d1117,stroke:#58a6ff,color:#c9d1d9 ``` **Key characteristics:** * You explicitly provide the CLI binary path * You are responsible for CLI version compatibility with the SDK * Authentication uses the signed-in user's credentials from the system keychain (or env vars) * Communication happens over stdio ## Configuration ### Using a local CLI binary
Node.js / TypeScript ```typescript import { CopilotClient } from "@github/copilot-sdk"; const client = new CopilotClient({ cliPath: "/usr/local/bin/copilot", }); const session = await client.createSession({ model: "gpt-4.1" }); const response = await session.sendAndWait({ prompt: "Hello!" }); console.log(response?.data.content); await client.stop(); ```
Python ```python from copilot import CopilotClient from copilot.generated.session_events import AssistantMessageData from copilot.session import PermissionHandler client = CopilotClient({ "cli_path": "/usr/local/bin/copilot", }) await client.start() session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model="gpt-4.1") response = await session.send_and_wait("Hello!") if response: match response.data: case AssistantMessageData() as data: print(data.content) await client.stop() ```
Go > [!NOTE] > The Go SDK does not bundle a CLI, so you must always provide `Connection`. ```go package main import ( "context" "fmt" "log" copilot "github.com/github/copilot-sdk/go" ) func main() { ctx := context.Background() client := copilot.NewClient(&copilot.ClientOptions{ Connection: copilot.StdioConnection{Path: "/usr/local/bin/copilot"}, }) if err := client.Start(ctx); err != nil { log.Fatal(err) } defer client.Stop() session, _ := client.CreateSession(ctx, &copilot.SessionConfig{Model: "gpt-4.1"}) response, _ := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "Hello!"}) if response != nil { if d, ok := response.Data.(*copilot.AssistantMessageData); ok { fmt.Println(d.Content) } } } ``` ```go client := copilot.NewClient(&copilot.ClientOptions{ Connection: copilot.StdioConnection{Path: "/usr/local/bin/copilot"}, }) if err := client.Start(ctx); err != nil { log.Fatal(err) } defer client.Stop() session, _ := client.CreateSession(ctx, &copilot.SessionConfig{Model: "gpt-4.1"}) response, _ := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "Hello!"}) if response != nil { if d, ok := response.Data.(*copilot.AssistantMessageData); ok { fmt.Println(d.Content) } } ```
.NET ```csharp var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForStdio(path: "/usr/local/bin/copilot"), }); await using var session = await client.CreateSessionAsync( new SessionConfig { Model = "gpt-4.1" }); var response = await session.SendAndWaitAsync( new MessageOptions { Prompt = "Hello!" }); Console.WriteLine(response?.Data.Content); ```
## Additional options ```typescript const client = new CopilotClient({ cliPath: "/usr/local/bin/copilot", // Set log level for debugging logLevel: "debug", // Pass extra CLI arguments cliArgs: ["--log-dir=/tmp/copilot-logs"], // Set working directory cwd: "/path/to/project", }); ``` ## Using environment variables Instead of the keychain, you can authenticate via environment variables. This is useful for CI or when you don't want interactive login. ```bash # Set one of these (in priority order): export COPILOT_GITHUB_TOKEN="gho_xxxx" # Recommended export GH_TOKEN="gho_xxxx" # GitHub CLI compatible export GITHUB_TOKEN="gho_xxxx" # GitHub Actions compatible ``` The SDK picks these up automatically—no code changes needed. ## Managing sessions Sessions default to ephemeral. To create resumable sessions, provide your own session ID: ```typescript // Create a named session const session = await client.createSession({ sessionId: "my-project-analysis", model: "gpt-4.1", }); // Later, resume it const resumed = await client.resumeSession("my-project-analysis"); ``` Session state is stored locally at `~/.copilot/session-state/{sessionId}/`. ## Limitations | Limitation | Details | |------------|---------| | **Version compatibility** | You must ensure your CLI version is compatible with the SDK | | **Single user** | Credentials are tied to whoever signed in to the CLI | | **Local only** | The CLI runs on the same machine as your app | | **No multi-tenant** | Can't serve multiple users from one CLI instance | ## Next steps * **[Default Setup](./bundled-cli.md)**: Use the SDK's built-in CLI (recommended for most use cases) * **[Getting Started tutorial](../getting-started.md)**: Build a complete interactive app * **[Authentication docs](../auth/authenticate.md)**: All auth methods in detail