From c690185d821c692c5437c9f972f8f9f768adc96f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 17:59:24 +0000 Subject: [PATCH 1/5] Initial plan From 39ab5e69a92e79f39df915d33f853575d7b00215 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 18:03:07 +0000 Subject: [PATCH 2/5] Add hide_cli_window option to suppress console window on Windows Co-authored-by: patniko <26906478+patniko@users.noreply.github.com> --- python/README.md | 1 + python/copilot/client.py | 9 +++++++++ python/copilot/types.py | 5 +++++ python/test_client.py | 14 ++++++++++++++ 4 files changed, 29 insertions(+) diff --git a/python/README.md b/python/README.md index 7aa11e1ab..0eabfb841 100644 --- a/python/README.md +++ b/python/README.md @@ -97,6 +97,7 @@ await client.stop() - `auto_restart` (bool): Auto-restart on crash (default: True) - `github_token` (str): GitHub token for authentication. When provided, takes priority over other auth methods. - `use_logged_in_user` (bool): Whether to use logged-in user for authentication (default: True, but False when `github_token` is provided). Cannot be used with `cli_url`. +- `hide_cli_window` (bool): Hide console window when spawning CLI process on Windows (default: False). Useful for GUI applications to prevent terminal windows from appearing. **SessionConfig Options (for `create_session`):** diff --git a/python/copilot/client.py b/python/copilot/client.py index 11669ddc9..24d74a1f3 100644 --- a/python/copilot/client.py +++ b/python/copilot/client.py @@ -184,6 +184,7 @@ def __init__(self, options: Optional[CopilotClientOptions] = None): "auto_start": opts.get("auto_start", True), "auto_restart": opts.get("auto_restart", True), "use_logged_in_user": use_logged_in_user, + "hide_cli_window": opts.get("hide_cli_window", False), } if opts.get("cli_url"): self.options["cli_url"] = opts["cli_url"] @@ -1167,6 +1168,12 @@ async def _start_cli_server(self) -> None: if self.options.get("github_token"): env["COPILOT_SDK_AUTH_TOKEN"] = self.options["github_token"] + # Prepare creation flags for Windows to hide console window if requested + creation_flags = 0 + if sys.platform == "win32" and self.options.get("hide_cli_window", False): + # CREATE_NO_WINDOW flag prevents console window from appearing on Windows + creation_flags = subprocess.CREATE_NO_WINDOW + # Choose transport mode if self.options["use_stdio"]: args.append("--stdio") @@ -1179,6 +1186,7 @@ async def _start_cli_server(self) -> None: bufsize=0, cwd=self.options["cwd"], env=env, + creationflags=creation_flags, ) else: if self.options["port"] > 0: @@ -1190,6 +1198,7 @@ async def _start_cli_server(self) -> None: stderr=subprocess.PIPE, cwd=self.options["cwd"], env=env, + creationflags=creation_flags, ) # For stdio mode, we're ready immediately diff --git a/python/copilot/types.py b/python/copilot/types.py index b77e36be1..c62f7d030 100644 --- a/python/copilot/types.py +++ b/python/copilot/types.py @@ -95,6 +95,11 @@ class CopilotClientOptions(TypedDict, total=False): # When False, only explicit tokens (github_token or environment variables) are used. # Default: True (but defaults to False when github_token is provided) use_logged_in_user: bool + # Whether to hide the console window when spawning the CLI process on Windows. + # When True, prevents the CLI subprocess from showing a console window on Windows. + # This is useful for GUI applications that should not display terminal windows. + # Default: False (console window is visible) + hide_cli_window: bool ToolResultType = Literal["success", "failure", "rejected", "denied"] diff --git a/python/test_client.py b/python/test_client.py index 7b4af8c0f..2f3e1ffe8 100644 --- a/python/test_client.py +++ b/python/test_client.py @@ -147,3 +147,17 @@ def test_use_logged_in_user_with_cli_url_raises(self): CopilotClient( {"cli_url": "localhost:8080", "use_logged_in_user": False, "log_level": "error"} ) + + +class TestHideCliWindow: + def test_hide_cli_window_default_false(self): + client = CopilotClient({"log_level": "error"}) + assert client.options.get("hide_cli_window") is False + + def test_hide_cli_window_explicit_true(self): + client = CopilotClient({"hide_cli_window": True, "log_level": "error"}) + assert client.options.get("hide_cli_window") is True + + def test_hide_cli_window_explicit_false(self): + client = CopilotClient({"hide_cli_window": False, "log_level": "error"}) + assert client.options.get("hide_cli_window") is False From 973f616b0eac6c685b58cd31a217b8b8e4aad7cd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 18:04:25 +0000 Subject: [PATCH 3/5] Address code review feedback: use conditional kwargs and idiomatic assertions Co-authored-by: patniko <26906478+patniko@users.noreply.github.com> --- python/copilot/client.py | 19 ++++++++++--------- python/test_client.py | 6 +++--- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/python/copilot/client.py b/python/copilot/client.py index 24d74a1f3..585de397e 100644 --- a/python/copilot/client.py +++ b/python/copilot/client.py @@ -1168,11 +1168,16 @@ async def _start_cli_server(self) -> None: if self.options.get("github_token"): env["COPILOT_SDK_AUTH_TOKEN"] = self.options["github_token"] - # Prepare creation flags for Windows to hide console window if requested - creation_flags = 0 + # Prepare subprocess kwargs + popen_kwargs = { + "cwd": self.options["cwd"], + "env": env, + } + + # Add creation flags for Windows to hide console window if requested if sys.platform == "win32" and self.options.get("hide_cli_window", False): # CREATE_NO_WINDOW flag prevents console window from appearing on Windows - creation_flags = subprocess.CREATE_NO_WINDOW + popen_kwargs["creationflags"] = subprocess.CREATE_NO_WINDOW # Choose transport mode if self.options["use_stdio"]: @@ -1184,9 +1189,7 @@ async def _start_cli_server(self) -> None: stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=0, - cwd=self.options["cwd"], - env=env, - creationflags=creation_flags, + **popen_kwargs, ) else: if self.options["port"] > 0: @@ -1196,9 +1199,7 @@ async def _start_cli_server(self) -> None: stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - cwd=self.options["cwd"], - env=env, - creationflags=creation_flags, + **popen_kwargs, ) # For stdio mode, we're ready immediately diff --git a/python/test_client.py b/python/test_client.py index 2f3e1ffe8..c4d27e6b0 100644 --- a/python/test_client.py +++ b/python/test_client.py @@ -152,12 +152,12 @@ def test_use_logged_in_user_with_cli_url_raises(self): class TestHideCliWindow: def test_hide_cli_window_default_false(self): client = CopilotClient({"log_level": "error"}) - assert client.options.get("hide_cli_window") is False + assert not client.options.get("hide_cli_window") def test_hide_cli_window_explicit_true(self): client = CopilotClient({"hide_cli_window": True, "log_level": "error"}) - assert client.options.get("hide_cli_window") is True + assert client.options.get("hide_cli_window") def test_hide_cli_window_explicit_false(self): client = CopilotClient({"hide_cli_window": False, "log_level": "error"}) - assert client.options.get("hide_cli_window") is False + assert not client.options.get("hide_cli_window") From ba043452c42481d28b9f80a033b061171401ba44 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Feb 2026 16:27:50 +0000 Subject: [PATCH 4/5] Make hiding CLI window default behavior across all SDKs - Python: Always hide window on Windows (removed hide_cli_window option) - Node.js: Add windowsHide: true to spawn options - Go: Add SysProcAttr with HideWindow on Windows via platform-specific files - .NET: Already had CreateNoWindow = true This ensures consistent behavior across all SDKs where the CLI subprocess console window is hidden on Windows to avoid distracting users in GUI apps. Co-authored-by: SteveSandersonMS <1101362+SteveSandersonMS@users.noreply.github.com> --- go/client.go | 3 +++ go/process_other.go | 11 +++++++++++ go/process_windows.go | 16 ++++++++++++++++ nodejs/src/client.ts | 2 ++ python/README.md | 3 ++- python/copilot/client.py | 6 ++---- python/copilot/types.py | 5 ----- python/test_client.py | 14 -------------- 8 files changed, 36 insertions(+), 24 deletions(-) create mode 100644 go/process_other.go create mode 100644 go/process_windows.go diff --git a/go/client.go b/go/client.go index 4db0f02c8..d383d9771 100644 --- a/go/client.go +++ b/go/client.go @@ -1056,6 +1056,9 @@ func (c *Client) startCLIServer(ctx context.Context) error { c.process = exec.CommandContext(ctx, command, args...) + // Configure platform-specific process attributes (e.g., hide window on Windows) + configureProcAttr(c.process) + // Set working directory if specified if c.options.Cwd != "" { c.process.Dir = c.options.Cwd diff --git a/go/process_other.go b/go/process_other.go new file mode 100644 index 000000000..7247fcc2f --- /dev/null +++ b/go/process_other.go @@ -0,0 +1,11 @@ +// go:build !windows + +package copilot + +import "os/exec" + +// configureProcAttr configures platform-specific process attributes. +// On non-Windows platforms, this is a no-op. +func configureProcAttr(cmd *exec.Cmd) { + // No special configuration needed on non-Windows platforms +} diff --git a/go/process_windows.go b/go/process_windows.go new file mode 100644 index 000000000..3e43f85f2 --- /dev/null +++ b/go/process_windows.go @@ -0,0 +1,16 @@ +// go:build windows + +package copilot + +import ( + "os/exec" + "syscall" +) + +// configureProcAttr configures platform-specific process attributes. +// On Windows, this hides the console window to avoid distracting users in GUI apps. +func configureProcAttr(cmd *exec.Cmd) { + cmd.SysProcAttr = &syscall.SysProcAttr{ + HideWindow: true, + } +} diff --git a/nodejs/src/client.ts b/nodejs/src/client.ts index 3dc61c440..507643632 100644 --- a/nodejs/src/client.ts +++ b/nodejs/src/client.ts @@ -1053,12 +1053,14 @@ export class CopilotClient { stdio: stdioConfig, cwd: this.options.cwd, env: envWithoutNodeDebug, + windowsHide: true, }); } else { this.cliProcess = spawn(this.options.cliPath, args, { stdio: stdioConfig, cwd: this.options.cwd, env: envWithoutNodeDebug, + windowsHide: true, }); } diff --git a/python/README.md b/python/README.md index 0eabfb841..d57d8ee53 100644 --- a/python/README.md +++ b/python/README.md @@ -97,7 +97,8 @@ await client.stop() - `auto_restart` (bool): Auto-restart on crash (default: True) - `github_token` (str): GitHub token for authentication. When provided, takes priority over other auth methods. - `use_logged_in_user` (bool): Whether to use logged-in user for authentication (default: True, but False when `github_token` is provided). Cannot be used with `cli_url`. -- `hide_cli_window` (bool): Hide console window when spawning CLI process on Windows (default: False). Useful for GUI applications to prevent terminal windows from appearing. + +> **Note:** On Windows, the SDK automatically hides the console window when spawning the CLI process to avoid distracting users in GUI applications. **SessionConfig Options (for `create_session`):** diff --git a/python/copilot/client.py b/python/copilot/client.py index 585de397e..48187a961 100644 --- a/python/copilot/client.py +++ b/python/copilot/client.py @@ -184,7 +184,6 @@ def __init__(self, options: Optional[CopilotClientOptions] = None): "auto_start": opts.get("auto_start", True), "auto_restart": opts.get("auto_restart", True), "use_logged_in_user": use_logged_in_user, - "hide_cli_window": opts.get("hide_cli_window", False), } if opts.get("cli_url"): self.options["cli_url"] = opts["cli_url"] @@ -1174,9 +1173,8 @@ async def _start_cli_server(self) -> None: "env": env, } - # Add creation flags for Windows to hide console window if requested - if sys.platform == "win32" and self.options.get("hide_cli_window", False): - # CREATE_NO_WINDOW flag prevents console window from appearing on Windows + # On Windows, hide the console window to avoid distracting users in GUI apps + if sys.platform == "win32": popen_kwargs["creationflags"] = subprocess.CREATE_NO_WINDOW # Choose transport mode diff --git a/python/copilot/types.py b/python/copilot/types.py index c62f7d030..b77e36be1 100644 --- a/python/copilot/types.py +++ b/python/copilot/types.py @@ -95,11 +95,6 @@ class CopilotClientOptions(TypedDict, total=False): # When False, only explicit tokens (github_token or environment variables) are used. # Default: True (but defaults to False when github_token is provided) use_logged_in_user: bool - # Whether to hide the console window when spawning the CLI process on Windows. - # When True, prevents the CLI subprocess from showing a console window on Windows. - # This is useful for GUI applications that should not display terminal windows. - # Default: False (console window is visible) - hide_cli_window: bool ToolResultType = Literal["success", "failure", "rejected", "denied"] diff --git a/python/test_client.py b/python/test_client.py index c4d27e6b0..7b4af8c0f 100644 --- a/python/test_client.py +++ b/python/test_client.py @@ -147,17 +147,3 @@ def test_use_logged_in_user_with_cli_url_raises(self): CopilotClient( {"cli_url": "localhost:8080", "use_logged_in_user": False, "log_level": "error"} ) - - -class TestHideCliWindow: - def test_hide_cli_window_default_false(self): - client = CopilotClient({"log_level": "error"}) - assert not client.options.get("hide_cli_window") - - def test_hide_cli_window_explicit_true(self): - client = CopilotClient({"hide_cli_window": True, "log_level": "error"}) - assert client.options.get("hide_cli_window") - - def test_hide_cli_window_explicit_false(self): - client = CopilotClient({"hide_cli_window": False, "log_level": "error"}) - assert not client.options.get("hide_cli_window") From c89912feb1f7f0213674a58dc096f2d636f97213 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 16 Feb 2026 16:58:32 +0000 Subject: [PATCH 5/5] Fix Go build --- go/process_other.go | 2 +- go/process_windows.go | 2 +- python/README.md | 2 -- python/copilot/client.py | 17 +++++++---------- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/go/process_other.go b/go/process_other.go index 7247fcc2f..5b3ba6353 100644 --- a/go/process_other.go +++ b/go/process_other.go @@ -1,4 +1,4 @@ -// go:build !windows +//go:build !windows package copilot diff --git a/go/process_windows.go b/go/process_windows.go index 3e43f85f2..37f954fca 100644 --- a/go/process_windows.go +++ b/go/process_windows.go @@ -1,4 +1,4 @@ -// go:build windows +//go:build windows package copilot diff --git a/python/README.md b/python/README.md index d57d8ee53..7aa11e1ab 100644 --- a/python/README.md +++ b/python/README.md @@ -98,8 +98,6 @@ await client.stop() - `github_token` (str): GitHub token for authentication. When provided, takes priority over other auth methods. - `use_logged_in_user` (bool): Whether to use logged-in user for authentication (default: True, but False when `github_token` is provided). Cannot be used with `cli_url`. -> **Note:** On Windows, the SDK automatically hides the console window when spawning the CLI process to avoid distracting users in GUI applications. - **SessionConfig Options (for `create_session`):** - `model` (str): Model to use ("gpt-5", "claude-sonnet-4.5", etc.). **Required when using custom provider.** diff --git a/python/copilot/client.py b/python/copilot/client.py index 48187a961..03be8ca11 100644 --- a/python/copilot/client.py +++ b/python/copilot/client.py @@ -1167,15 +1167,8 @@ async def _start_cli_server(self) -> None: if self.options.get("github_token"): env["COPILOT_SDK_AUTH_TOKEN"] = self.options["github_token"] - # Prepare subprocess kwargs - popen_kwargs = { - "cwd": self.options["cwd"], - "env": env, - } - # On Windows, hide the console window to avoid distracting users in GUI apps - if sys.platform == "win32": - popen_kwargs["creationflags"] = subprocess.CREATE_NO_WINDOW + creationflags = subprocess.CREATE_NO_WINDOW if sys.platform == "win32" else 0 # Choose transport mode if self.options["use_stdio"]: @@ -1187,7 +1180,9 @@ async def _start_cli_server(self) -> None: stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=0, - **popen_kwargs, + cwd=self.options["cwd"], + env=env, + creationflags=creationflags, ) else: if self.options["port"] > 0: @@ -1197,7 +1192,9 @@ async def _start_cli_server(self) -> None: stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - **popen_kwargs, + cwd=self.options["cwd"], + env=env, + creationflags=creationflags, ) # For stdio mode, we're ready immediately