Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions go/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,18 @@ func main() {
}
```

## Distributing your application with an embedded GitHub Copilot CLI

The SDK supports bundling, using Go's `embed` package, the Copilot CLI binary within your application's distribution.
This allows you to bundle a specific CLI version and avoid external dependencies on the user's system.

Follow these steps to embed the CLI:

1. Run `go get -tool github.com/github/copilot-sdk/go/cmd/bundler`. This is a one-time setup step per project.
2. Run `go tool bundler` in your build environment just before building your application.

That's it! When your application calls `copilot.NewClient` without a `CLIPath` nor the `COPILOT_CLI_PATH` environment variable, the SDK will automatically install the embedded CLI to a cache directory and use it for all operations.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cross-SDK consistency note: Consider adding a comparison section here explaining why Go requires manual bundling while Node.js, Python, and .NET SDKs have the CLI automatically bundled.

For example:

> **Note**: Unlike the Node.js, Python, and .NET SDKs where the CLI is automatically bundled with the package, the Go SDK requires you to explicitly run the bundler tool. This keeps the Go module size small and gives you control over which CLI version to embed.

This would help users understand the different approach and set appropriate expectations.

AI generated by SDK Consistency Review Agent for #414


## API Reference

### Client
Expand Down
18 changes: 14 additions & 4 deletions go/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import (
"sync"
"time"

"github.com/github/copilot-sdk/go/internal/embeddedcli"
"github.com/github/copilot-sdk/go/internal/jsonrpc2"
)

Expand Down Expand Up @@ -102,7 +103,7 @@ type Client struct {
// })
func NewClient(options *ClientOptions) *Client {
opts := ClientOptions{
CLIPath: "copilot",
CLIPath: "",
Cwd: "",
Port: 0,
LogLevel: "info",
Expand Down Expand Up @@ -1313,6 +1314,15 @@ func (c *Client) verifyProtocolVersion(ctx context.Context) error {
// This spawns the CLI server as a subprocess using the configured transport
// mode (stdio or TCP).
func (c *Client) startCLIServer(ctx context.Context) error {
cliPath := c.options.CLIPath
if cliPath == "" {
// If no CLI path is provided, attempt to use the embedded CLI if available
cliPath = embeddedcli.Path()
}
if cliPath == "" {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good consistency: This fallback logic (embedded → "copilot" in PATH) matches the behavior in other SDKs nicely.

However, when the CLI is not found, consider if the error message should mention running go tool bundler to help users who haven't embedded the CLI yet. For comparison:

  • Python SDK raises: "Copilot CLI not found. The bundled CLI binary is not available. Ensure you installed a platform-specific wheel, or provide cli_path."
  • .NET SDK throws: "Copilot CLI not found at '{searchedPath}'. Ensure the SDK NuGet package was restored correctly or provide an explicit CliPath."

A similar helpful message for Go might be: "Copilot CLI not found. Run 'go tool bundler' to embed the CLI, ensure 'copilot' is in PATH, or provide CLIPath option."

AI generated by SDK Consistency Review Agent for #414

// Default to "copilot" in PATH if no embedded CLI is available and no custom path is set
cliPath = "copilot"
}
args := []string{"--headless", "--no-auto-update", "--log-level", c.options.LogLevel}

// Choose transport mode
Expand All @@ -1339,10 +1349,10 @@ func (c *Client) startCLIServer(ctx context.Context) error {

// If CLIPath is a .js file, run it with node
// Note we can't rely on the shebang as Windows doesn't support it
command := c.options.CLIPath
if strings.HasSuffix(c.options.CLIPath, ".js") {
command := cliPath
if strings.HasSuffix(cliPath, ".js") {
command = "node"
args = append([]string{c.options.CLIPath}, args...)
args = append([]string{cliPath}, args...)
}

c.process = exec.CommandContext(ctx, command, args...)
Expand Down
Loading
Loading