From d982aebe68387494f1a5113d4f9a86fd5ad149e9 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 6 May 2026 03:40:16 +0000 Subject: [PATCH] fix(cli_driver): place extra_args before prompt positional Bugbot flagged that `run_claude` placed the prompt as cmd[7] and then appended extra_args after it. `claude --print` takes the prompt as the final positional argument; flags appearing after it (e.g. `--allowed-tools Bash`, `--image `) are swallowed by the prompt parser, which silently breaks the tool_use and vision cells. Build the flag list first, then append the prompt last. Add a unit test that pins the ordering. Co-authored-by: Mateo Wang --- .../_driver_unit_tests/test_cli_driver.py | 23 +++++++++++++++++++ tests/claude_code/cli_driver.py | 7 +++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/tests/claude_code/_driver_unit_tests/test_cli_driver.py b/tests/claude_code/_driver_unit_tests/test_cli_driver.py index 4766111c08a..073b1559504 100644 --- a/tests/claude_code/_driver_unit_tests/test_cli_driver.py +++ b/tests/claude_code/_driver_unit_tests/test_cli_driver.py @@ -63,6 +63,29 @@ def test_run_claude_assembles_command_correctly(): assert cmd[-1] == "hello" +def test_run_claude_places_extra_args_before_prompt(): + """`claude --print` expects the prompt as the final positional arg. + + Flags appearing after the prompt are ignored or eaten by the prompt + parser, which silently broke the tool_use and vision cells before the + fix. Pin the ordering: every flag (including caller-supplied + `extra_args`) must precede the prompt. + """ + runner, captured = _make_runner(stdout="") + run_claude( + prompt="say hi", + model="claude-haiku-4-5", + base_url="http://localhost:4000", + api_key="sk-test", + extra_args=["--allowed-tools", "Bash"], + runner=runner, + ) + cmd = captured["cmd"] + assert cmd[-1] == "say hi" + prompt_idx = cmd.index("say hi") + assert cmd[prompt_idx - 2 : prompt_idx] == ["--allowed-tools", "Bash"] + + def test_run_claude_overlays_proxy_env(): runner, captured = _make_runner(stdout="") run_claude( diff --git a/tests/claude_code/cli_driver.py b/tests/claude_code/cli_driver.py index c15b38bcb72..d4ec7667bbb 100644 --- a/tests/claude_code/cli_driver.py +++ b/tests/claude_code/cli_driver.py @@ -78,6 +78,11 @@ def run_claude( if not api_key: raise ValueError("api_key must be a non-empty string") + # `claude --print` takes the prompt as the **last positional argument**. + # Flags must come before it, otherwise they're parsed as part of the + # prompt (or silently dropped, depending on the CLI version) and the + # tool_use / vision cells fail with confusing "no tool_use observed" + # errors. Build the flag list first, then append the prompt last. cmd: List[str] = [ cli_path, "--print", @@ -86,10 +91,10 @@ def run_claude( "--verbose", "--model", model, - prompt, ] if extra_args: cmd.extend(extra_args) + cmd.append(prompt) env = {**os.environ, **(extra_env or {})} env["ANTHROPIC_BASE_URL"] = base_url