Summary
Several CopilotClientOptions are implemented by lowering them to environment variables set on the spawned CLI child process. With the new in-process (FFI) transport (RuntimeConnection.ForInProcess() / Transport::InProcess / forInProcess()), there is no child process the SDK controls the environment of for these values, so these options are not honored in-process. This affects all SDKs adding the in-process transport (.NET already merged; TypeScript and Rust in progress on stevesa/ffi-inproc-rust-ts).
This issue tracks the gap and the fact that the current workaround is to set the corresponding environment variable on the host/parent process yourself before constructing the client.
Why it happens
For stdio/TCP, the SDK spawns a child process and populates startInfo.Environment (or the equivalent), so per-client values are coherent — each client owns its own OS process.
For in-process, the native runtime cdylib is loaded into the shared host process, and host-side native reads consult the ambient host process environment, not a per-client env block. .NET's ValidateEnvironmentOptions therefore rejects Environment/Telemetry for in-process, and the in-process start path passes an effectively empty env to host_start — so the remaining env-lowered options are simply never applied.
Complete list of options lowered to env vars (from dotnet/src/Client.cs)
| Option |
Env var(s) |
In-process behavior today |
Environment |
(replaces whole env block) |
Rejected (throws) |
Telemetry |
COPILOT_OTEL_ENABLED, OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_PROTOCOL, COPILOT_OTEL_FILE_EXPORTER_PATH, COPILOT_OTEL_EXPORTER_TYPE, COPILOT_OTEL_SOURCE_NAME, OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT |
Rejected (throws) |
GitHubToken |
COPILOT_SDK_AUTH_TOKEN (+ --auth-token-env CLI arg) |
Silently ignored |
BaseDirectory |
COPILOT_HOME |
Silently ignored |
Mode == Empty |
COPILOT_DISABLE_KEYTAR=1 |
Silently ignored |
ConnectionToken (TCP only) |
COPILOT_CONNECTION_TOKEN |
N/A (no TCP in-process) |
Note: UseLoggedInUser, SessionIdleTimeoutSeconds, EnableRemoteSessions, LogLevel are lowered to CLI args (--no-auto-login, --session-idle-timeout, --remote, --log-level), not env vars — but the FFI host_start argv is [entrypoint, --embedded-host] and does not forward these either, so they are a related (separate) in-process gap worth confirming.
Current workaround
Set the environment variable on the host/parent process before creating the client, e.g.:
- Auth: export
COPILOT_SDK_AUTH_TOKEN (or ensure ambient GH_TOKEN/GITHUB_TOKEN are valid) instead of GitHubToken.
- Home: export
COPILOT_HOME instead of BaseDirectory.
- Keytar: export
COPILOT_DISABLE_KEYTAR=1 instead of relying on Mode = Empty.
- Telemetry: export the
COPILOT_OTEL_* / OTEL_* vars instead of Telemetry.
Proper long-term fix
These should all become first-class server-level options, not reliant on being passed as env vars. The runtime code can continue to look for env vars as an override for back-compat.
Acceptance / follow-ups
Refs: dotnet/src/Client.cs ValidateEnvironmentOptions (~L215), in-process start (~L339-353), child-process env block (~L2079-2105), ApplyTelemetryEnvironment (~L1971), auth arg (~L2029). Related PRs: #1901, #1920, #1929, #1930.
Summary
Several
CopilotClientOptionsare implemented by lowering them to environment variables set on the spawned CLI child process. With the new in-process (FFI) transport (RuntimeConnection.ForInProcess()/Transport::InProcess/forInProcess()), there is no child process the SDK controls the environment of for these values, so these options are not honored in-process. This affects all SDKs adding the in-process transport (.NET already merged; TypeScript and Rust in progress onstevesa/ffi-inproc-rust-ts).This issue tracks the gap and the fact that the current workaround is to set the corresponding environment variable on the host/parent process yourself before constructing the client.
Why it happens
For stdio/TCP, the SDK spawns a child process and populates
startInfo.Environment(or the equivalent), so per-client values are coherent — each client owns its own OS process.For in-process, the native runtime cdylib is loaded into the shared host process, and host-side native reads consult the ambient host process environment, not a per-client env block. .NET's
ValidateEnvironmentOptionstherefore rejectsEnvironment/Telemetryfor in-process, and the in-process start path passes an effectively empty env tohost_start— so the remaining env-lowered options are simply never applied.Complete list of options lowered to env vars (from
dotnet/src/Client.cs)EnvironmentTelemetryCOPILOT_OTEL_ENABLED,OTEL_EXPORTER_OTLP_ENDPOINT,OTEL_EXPORTER_OTLP_PROTOCOL,COPILOT_OTEL_FILE_EXPORTER_PATH,COPILOT_OTEL_EXPORTER_TYPE,COPILOT_OTEL_SOURCE_NAME,OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENTGitHubTokenCOPILOT_SDK_AUTH_TOKEN(+--auth-token-envCLI arg)BaseDirectoryCOPILOT_HOMEMode == EmptyCOPILOT_DISABLE_KEYTAR=1ConnectionToken(TCP only)COPILOT_CONNECTION_TOKENNote:
UseLoggedInUser,SessionIdleTimeoutSeconds,EnableRemoteSessions,LogLevelare lowered to CLI args (--no-auto-login,--session-idle-timeout,--remote,--log-level), not env vars — but the FFIhost_startargv is[entrypoint, --embedded-host]and does not forward these either, so they are a related (separate) in-process gap worth confirming.Current workaround
Set the environment variable on the host/parent process before creating the client, e.g.:
COPILOT_SDK_AUTH_TOKEN(or ensure ambientGH_TOKEN/GITHUB_TOKENare valid) instead ofGitHubToken.COPILOT_HOMEinstead ofBaseDirectory.COPILOT_DISABLE_KEYTAR=1instead of relying onMode = Empty.COPILOT_OTEL_*/OTEL_*vars instead ofTelemetry.Proper long-term fix
These should all become first-class server-level options, not reliant on being passed as env vars. The runtime code can continue to look for env vars as an override for back-compat.
Acceptance / follow-ups
Environment/Telemetrythrow;GitHubToken/BaseDirectory/keytar silently no-op).host_startenv_jsonin host-side reads so per-client env is coherent in-process.UseLoggedInUser, idle timeout, remote, log level) in-process.Refs:
dotnet/src/Client.csValidateEnvironmentOptions(~L215), in-process start (~L339-353), child-process env block (~L2079-2105),ApplyTelemetryEnvironment(~L1971), auth arg (~L2029). Related PRs: #1901, #1920, #1929, #1930.