{"meta":{"title":"Using a bundled CLI with Copilot SDK","intro":"Package Copilot CLI alongside your application so that users do not need to install or configure anything separately.","product":"GitHub Copilot","breadcrumbs":[{"href":"/en/copilot","title":"GitHub Copilot"},{"href":"/en/copilot/how-tos","title":"How-tos"},{"href":"/en/copilot/how-tos/copilot-sdk","title":"Copilot SDK"},{"href":"/en/copilot/how-tos/copilot-sdk/set-up-copilot-sdk","title":"Set up Copilot SDK"},{"href":"/en/copilot/how-tos/copilot-sdk/set-up-copilot-sdk/bundled-cli","title":"Bundled CLI"}],"documentType":"article"},"body":"# Using a bundled CLI with Copilot SDK\n\nPackage Copilot CLI alongside your application so that users do not need to install or configure anything separately.\n\n> \\[!NOTE]\n> Copilot SDK is currently in technical preview. Functionality and availability are subject to change.\n\nShip Copilot CLI as part of your application so your users can get started with no additional setup.\n\n**Best for:** Desktop apps, standalone tools, Electron apps, and distributable CLI utilities.\n\n## How it works\n\nInstead of relying on a globally installed CLI, you include the CLI binary in your application bundle. The SDK points to your bundled copy via the `cliPath` option. Key characteristics are:\n\n* The CLI binary ships with your app—no separate install is needed.\n* You control the exact CLI version your app uses.\n* Users authenticate through your app, environment variables, or BYOK.\n* Sessions are managed per user on their machine.\n\n## Setup\n\n### Step 1: Include the CLI in your project\n\nThe CLI is distributed as part of the `@github/copilot` npm package.\n\n```shell\nnpm install @github/copilot\n```\n\n### Step 2: Point the SDK to your bundled CLI\n\n#### Node.js / TypeScript\n\n```typescript\nimport { CopilotClient } from \"@github/copilot-sdk\";\nimport path from \"path\";\n\nconst client = new CopilotClient({\n    // Point to the CLI binary in your app bundle\n    cliPath: path.join(__dirname, \"vendor\", \"copilot\"),\n});\n\nconst session = await client.createSession({ model: \"gpt-4.1\" });\nconst response = await session.sendAndWait({ prompt: \"Hello!\" });\nconsole.log(response?.data.content);\n\nawait client.stop();\n```\n\n#### Python\n\n```python\nfrom copilot import CopilotClient, PermissionHandler\nfrom pathlib import Path\n\nclient = CopilotClient({\n    \"cli_path\": str(Path(__file__).parent / \"vendor\" / \"copilot\"),\n})\nawait client.start()\n\nsession = await client.create_session(on_permission_request=PermissionHandler.approve_all, model=\"gpt-4.1\")\nresponse = await session.send_and_wait({\"prompt\": \"Hello!\"})\nprint(response.data.content)\n\nawait client.stop()\n```\n\n#### Go\n\n```golang\nclient := copilot.NewClient(&copilot.ClientOptions{\n    CLIPath: \"./vendor/copilot\",\n})\nif err := client.Start(ctx); err != nil {\n    log.Fatal(err)\n}\ndefer client.Stop()\n\nsession, _ := client.CreateSession(ctx, &copilot.SessionConfig{Model: \"gpt-4.1\"})\nresponse, _ := session.SendAndWait(ctx, copilot.MessageOptions{Prompt: \"Hello!\"})\nfmt.Println(*response.Data.Content)\n```\n\n#### .NET\n\n```csharp\nvar client = new CopilotClient(new CopilotClientOptions\n{\n    CliPath = Path.Combine(AppContext.BaseDirectory, \"vendor\", \"copilot\"),\n});\n\nawait using var session = await client.CreateSessionAsync(\n    new SessionConfig { Model = \"gpt-4.1\" });\n\nvar response = await session.SendAndWaitAsync(\n    new MessageOptions { Prompt = \"Hello!\" });\nConsole.WriteLine(response?.Data.Content);\n```\n\n## Authentication strategies\n\nWhen bundling the CLI, you need to decide how your users will authenticate. The following diagram illustrates common patterns.\n\n![Diagram showing authentication strategy options for a bundled CLI deployment.](/assets/images/help/copilot/copilot-sdk/bundled-cli-authentication-strategies.png)\n\n### Option A: User's signed-in credentials (simplest)\n\nThe user signs in to the CLI once, and your bundled app uses those credentials. No extra code needed—this is the default behavior.\n\n```typescript\nconst client = new CopilotClient({\n    cliPath: path.join(__dirname, \"vendor\", \"copilot\"),\n    // Default: uses signed-in user credentials\n});\n```\n\n### Option B: Token via environment variable\n\nSet a token programmatically or instruct users to set one before starting your app:\n\n```typescript\nconst client = new CopilotClient({\n    cliPath: path.join(__dirname, \"vendor\", \"copilot\"),\n    env: {\n        COPILOT_GITHUB_TOKEN: getUserToken(),\n    },\n});\n```\n\nReplace `getUserToken()` with the logic in your app that retrieves the user's GitHub OAuth token.\n\n### Option C: BYOK (no GitHub authentication needed)\n\nIf you manage your own model provider keys, users don't need GitHub accounts:\n\n```typescript\nconst client = new CopilotClient({\n    cliPath: path.join(__dirname, \"vendor\", \"copilot\"),\n});\n\nconst session = await client.createSession({\n    model: \"gpt-4.1\",\n    provider: {\n        type: \"openai\",\n        baseUrl: \"https://api.openai.com/v1\",\n        apiKey: process.env.OPENAI_API_KEY,\n    },\n});\n```\n\n## Session management\n\nBundled apps typically want named sessions so users can resume conversations:\n\n```typescript\nconst client = new CopilotClient({\n    cliPath: path.join(__dirname, \"vendor\", \"copilot\"),\n});\n\n// Create a session tied to the user's project\nconst sessionId = `project-${projectName}`;\nconst session = await client.createSession({\n    sessionId,\n    model: \"gpt-4.1\",\n});\n\n// Resume the session in a later run\nconst resumed = await client.resumeSession(sessionId);\n```\n\nSession state is stored at `~/.copilot/session-state/SESSION-ID/`, where `SESSION-ID` is the session ID you provided.\n\n## Distribution patterns\n\n### Desktop app (Electron, Tauri)\n\nInclude the CLI binary in your app's resources directory:\n\n```typescript\nimport { app } from \"electron\";\nimport path from \"path\";\n\nconst cliPath = path.join(\n    app.isPackaged ? process.resourcesPath : __dirname,\n    \"copilot\"\n);\n\nconst client = new CopilotClient({ cliPath });\n```\n\n### CLI tool\n\nFor distributable CLI tools, resolve the path relative to your binary:\n\n```typescript\nimport { fileURLToPath } from \"url\";\nimport path from \"path\";\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst cliPath = path.join(__dirname, \"..\", \"vendor\", \"copilot\");\n\nconst client = new CopilotClient({ cliPath });\n```\n\n## Platform-specific binaries\n\nWhen distributing for multiple platforms, include the correct binary for each target:\n\n```text\nmy-app/\n├── vendor/\n│   ├── copilot-darwin-arm64    # macOS Apple Silicon\n│   ├── copilot-darwin-x64      # macOS Intel\n│   ├── copilot-linux-x64       # Linux x64\n│   └── copilot-win-x64.exe     # Windows x64\n└── src/\n    └── index.ts\n```\n\n```typescript\nimport os from \"os\";\n\nfunction getCLIPath(): string {\n    const platform = process.platform;   // \"darwin\", \"linux\", \"win32\"\n    const arch = os.arch();              // \"arm64\", \"x64\"\n    const ext = platform === \"win32\" ? \".exe\" : \"\";\n    const name = `copilot-${platform}-${arch}${ext}`;\n    return path.join(__dirname, \"vendor\", name);\n}\n\nconst client = new CopilotClient({\n    cliPath: getCLIPath(),\n});\n```\n\n## Limitations\n\n| Limitation          | Details                                                |\n| ------------------- | ------------------------------------------------------ |\n| **Bundle size**     | The CLI binary adds to your app's distribution size.   |\n| **Updates**         | You manage CLI version updates in your release cycle.  |\n| **Platform builds** | Separate binaries are needed for each OS/architecture. |\n| **Single user**     | Each bundled CLI instance serves one user.             |\n\n## Next steps\n\n* For users signing in with GitHub accounts, see [Using GitHub OAuth with Copilot SDK](/en/copilot/how-tos/copilot-sdk/set-up-copilot-sdk/github-oauth).\n* To run on a server instead of user machines, see [Setting up Copilot SDK for backend services](/en/copilot/how-tos/copilot-sdk/set-up-copilot-sdk/backend-services).\n* For installation and your first message, see [Getting started with Copilot SDK](/en/copilot/how-tos/copilot-sdk/sdk-getting-started)."}