From 5ee98f05c1c4989c8d6cb8a31dcffafa6dbfa6fc Mon Sep 17 00:00:00 2001 From: VihaanAgarwal Date: Tue, 14 Jul 2026 13:31:57 -0700 Subject: [PATCH] fix(transport): forward max_turns=0 to the CLI instead of dropping it The command builder guarded max_turns with a truthiness check, so max_turns=0 was treated the same as the None "unset" sentinel and the --max-turns flag was never emitted. A caller that sets 0 (for example a turn budget decremented down to zero) silently got the CLI default of no turn limit instead. Every other numeric option in _build_command already guards on `is not None` (max_budget_usd, task_budget, max_thinking_tokens), so 0 is forwarded there. Match that here and let the CLI decide what 0 means. --- .../_internal/transport/subprocess_cli.py | 2 +- tests/test_transport.py | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/claude_agent_sdk/_internal/transport/subprocess_cli.py b/src/claude_agent_sdk/_internal/transport/subprocess_cli.py index e9a522d13..88c230930 100644 --- a/src/claude_agent_sdk/_internal/transport/subprocess_cli.py +++ b/src/claude_agent_sdk/_internal/transport/subprocess_cli.py @@ -317,7 +317,7 @@ def _build_command(self) -> list[str]: if effective_allowed_tools: cmd.extend(["--allowedTools", ",".join(effective_allowed_tools)]) - if self._options.max_turns: + if self._options.max_turns is not None: cmd.extend(["--max-turns", str(self._options.max_turns)]) if self._options.max_budget_usd is not None: diff --git a/tests/test_transport.py b/tests/test_transport.py index d55aa18b0..129fd769f 100644 --- a/tests/test_transport.py +++ b/tests/test_transport.py @@ -208,6 +208,26 @@ def test_build_command_with_options(self): assert "--max-turns" in cmd assert "5" in cmd + def test_build_command_max_turns_zero(self): + """max_turns=0 is a caller-supplied value and must be forwarded. + + None is the "unset" sentinel; 0 is an explicit cap and should reach the + CLI like the other numeric options (max_budget_usd, task_budget, + max_thinking_tokens all forward 0 via ``is not None``). + """ + transport = SubprocessCLITransport( + prompt="test", + options=make_options(max_turns=0), + ) + + cmd = transport._build_command() + assert "--max-turns" in cmd + assert cmd[cmd.index("--max-turns") + 1] == "0" + + # None still means "unset" — no flag emitted. + transport_unset = SubprocessCLITransport(prompt="test", options=make_options()) + assert "--max-turns" not in transport_unset._build_command() + def test_build_command_with_dont_ask_permission_mode(self): """Test building CLI command with dontAsk permission mode.""" transport = SubprocessCLITransport(