# How to Create a CopilotClient Instance in Your Node.js Application

> Learn how to create a CopilotClient instance in Node.js. Import and instantiate the class from @github/copilot-sdk, choosing your transport mode for seamless integration.

- Repository: [GitHub/copilot-sdk](https://github.com/github/copilot-sdk)
- Tags: how-to-guide
- Published: 2026-07-18

---

**To create a CopilotClient instance, import the `CopilotClient` class from `@github/copilot-sdk` and instantiate it with optional `CopilotClientOptions`, selecting your transport mode via the `RuntimeConnection` factory methods.**

The `github/copilot-sdk` repository provides the official Node.js SDK for integrating GitHub Copilot into your applications. This guide walks through the instantiation patterns found in the source code, from basic stdio transport to advanced TCP and in-process configurations.

## Importing the CopilotClient Class

The entry point for the SDK is the `CopilotClient` class defined in [[`nodejs/src/client.ts`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/client.ts)](https://github.com/github/copilot-sdk/blob/main/nodejs/src/client.ts). Before creating an instance, install the package and import the necessary constructors.

```typescript
import { CopilotClient, RuntimeConnection } from "@github/copilot-sdk";

```

The `RuntimeConnection` factory, defined in [[`nodejs/src/types.ts`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/types.ts)](https://github.com/github/copilot-sdk/blob/main/nodejs/src/types.ts), provides static methods to configure how your client connects to the Copilot runtime.

## Understanding Connection Modes

The `CopilotClient` constructor accepts a `CopilotClientOptions` object that specifies the transport mechanism. According to the source code at [`line 96`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/client.ts#L96), the constructor resolves the requested transport, validates incompatible option combinations, and stores the effective environment for later use.

### Default stdio Transport (Spawn Bundled CLI)

If you provide no `connection` option, the client defaults to `RuntimeConnection.forStdio()`, which spawns the bundled CLI binary and communicates over stdio streams. This is handled by the `resolveDefaultConnection` logic at [`lines 81-86`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/client.ts#L81-L86) of [`client.ts`](https://github.com/github/copilot-sdk/blob/main/client.ts).

```typescript
const client = new CopilotClient();

```

The SDK automatically locates the appropriate platform-specific package using `getBundledCliPath()` at [`lines 72-88`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/client.ts#L72-L88).

### TCP Connection

To spawn a runtime that listens on a TCP socket, use `RuntimeConnection.forTcp()`. Pass `port: 0` to auto-allocate an available port.

```typescript
const client = new CopilotClient({
  connection: RuntimeConnection.forTcp({ port: 9001 }),
});

```

### URI Connection (External Server)

Connect to an already-running Copilot server by specifying a URI. This pattern is useful when managing the runtime lifecycle separately from your application.

```typescript
const client = new CopilotClient({
  connection: RuntimeConnection.forUri("localhost:3000"),
});

```

### In-Process Runtime (Experimental)

For scenarios requiring the native runtime library loaded directly into your process, use the experimental `forInProcess()` factory.

```typescript
const client = new CopilotClient({
  connection: RuntimeConnection.forInProcess(),
});

```

### Custom CLI Binary

Override the default bundled CLI by providing a path to a custom binary. This is useful when testing patched versions or platform-specific builds.

```typescript
const client = new CopilotClient({
  connection: RuntimeConnection.forStdio({ path: "/usr/local/bin/copilot" }),
  logLevel: "debug",
});

```

## Configuring Client Options

The `CopilotClientOptions` interface at [`lines 63-132`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/types.ts#L63-L132) of [`types.ts`](https://github.com/github/copilot-sdk/blob/main/types.ts) defines additional configuration fields:

- **`workingDirectory`**: Sets the runtime's startup directory.
- **`baseDirectory`**: Overrides the default `~/.copilot` data location.
- **`gitHubToken`**: Provides explicit authentication (note: incompatible with URI connections).
- **`telemetry`**: Configures OpenTelemetry export via `otlpEndpoint`.
- **`sessionFs`**: Registers a custom session-filesystem provider.
- **`logLevel`**: Controls debug output verbosity.

```typescript
const client = new CopilotClient({
  connection: RuntimeConnection.forStdio(),
  workingDirectory: "/my/project",
  gitHubToken: process.env.COPILOT_TOKEN,
  logLevel: "debug",
});

```

## Starting the Client and Creating Sessions

The Copilot runtime uses **lazy initialization**. Instantiation only prepares the connection parameters; the actual process spawn or network connection occurs when you explicitly call `client.start()` or implicitly via `client.createSession()`.

The start logic performs four steps:
1. **Connection resolution** – Selects transport based on the `connection` option or the `COPILOT_SDK_DEFAULT_CONNECTION` environment variable.
2. **Environment preparation** – Merges client-level `env` with transport-level `env` for child-process transports.
3. **CLI binary location** – Resolves the platform package path for stdio transports.
4. **Protocol handshake** – Establishes the JSON-RPC connection and validates protocol versions.

```typescript
async function initialize() {
  const client = new CopilotClient({
    connection: RuntimeConnection.forTcp({ port: 0 }),
    logLevel: "debug",
  });

  // Explicit start (optional - createSession() does this automatically)
  await client.start();
  
  return client;
}

```

Once started, create a session to interact with Copilot:

```typescript
import { approveAll } from "@github/copilot-sdk";

async function run() {
  const client = await initialize();
  
  const session = await client.createSession({
    onPermissionRequest: approveAll,
    model: "gpt-4o",
  });

  await session.send({ 
    prompt: "Explain the difference between let and const in JavaScript." 
  });
}

```

## Summary

- **Import** `CopilotClient` and `RuntimeConnection` from `@github/copilot-sdk` to begin instantiation.
- **Choose a transport**: Use `forStdio()` (default), `forTcp()`, `forUri()`, or `forInProcess()` from the `RuntimeConnection` factory.
- **Configure options** via `CopilotClientOptions` to set working directories, authentication tokens, and telemetry endpoints as defined in [`nodejs/src/types.ts`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/types.ts).
- **Lazy start**: The runtime spawns only when you call `client.start()` or `client.createSession()`, with connection logic centralized in [`nodejs/src/client.ts`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/client.ts).

## Frequently Asked Questions

### What happens if I don't specify a connection when creating a CopilotClient?

If no `connection` option is provided, the constructor defaults to `RuntimeConnection.forStdio()`, which spawns the bundled Copilot CLI binary and communicates over stdio streams. The SDK locates the correct binary for your platform using the `getBundledCliPath()` method.

### Can I connect to an existing Copilot server instead of spawning a new process?

Yes. Use `RuntimeConnection.forUri("host:port")` in your `CopilotClientOptions` to connect to an external server. This is useful when the runtime is managed by an orchestrator or runs as a persistent service, though you cannot use `gitHubToken` authentication with URI connections according to the validation logic in the constructor.

### How do I provide authentication tokens when creating a client?

Pass the `gitHubToken` field in your `CopilotClientOptions` object. The constructor stores this token at [`lines 122-130`](https://github.com/github/copilot-sdk/blob/main/nodejs/src/client.ts#L122-L130) for use during the RPC handshake. Note that this option is validated as incompatible with URI-based connections, which must handle authentication separately.

### When should I use in-process transport versus stdio?

Use `RuntimeConnection.forInProcess()` when you need minimal latency by loading the native runtime library directly into your Node.js process; this is marked as experimental in the source. Use `forStdio()` (the default) for stability and isolation, as it spawns the CLI as a separate process with stdio-based JSON-RPC communication.