# Local CLI setup Use a specific CLI binary instead of the SDK's automatic CLI management. 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.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