Skip to content

Two Bugs: Large --agents and --system-prompt fail on Windows due to command line limits #501

@0xeb

Description

@0xeb

Two Bugs: Large --agents and --system-prompt fail on Windows due to command line limits

Summary

This issue documents two related but distinct bugs that affect Windows users (and potentially other platforms with large configurations):

Bug 1: @filepath syntax for --agents not supported by CLI

The Python SDK explicitly uses @filepath syntax when the command line exceeds length limits.

SDK source reference (subprocess_cli.py lines 336-362):

# Check if command line is too long (Windows limitation)
cmd_str = " ".join(cmd)
if len(cmd_str) > _CMD_LENGTH_LIMIT and self._options.agents:
    # Command is too long - use temp file for agents
    # Find the --agents argument and replace its value with @filepath
    try:
        agents_idx = cmd.index("--agents")
        agents_json_value = cmd[agents_idx + 1]

        # Create a temporary file
        temp_file = tempfile.NamedTemporaryFile(
            mode="w", suffix=".json", delete=False, encoding="utf-8"
        )
        temp_file.write(agents_json_value)
        temp_file.close()

        # Replace agents JSON with @filepath reference
        cmd[agents_idx + 1] = f"@{temp_file.name}"  # <-- HERE: SDK uses @ prefix

However, the CLI does not support this @ prefix syntax - it tries to parse the literal string @C:\path\... as JSON, which fails.

Bug 2: No file support for large --system-prompt values

There is no mechanism to pass large system prompts via file:

  • No --system-prompt-file CLI flag
  • No @filepath support
  • No temp file fallback in the SDK (unlike --agents)

This means system prompts >8KB on Windows will fail, especially when combined with MCP servers or agents.

Reproduction status: Both bugs confirmed and reproducible on Windows (see test scripts below).

Environment (Verified Reproduction)

  • Python SDK: 0.1.19 (installed from source)
  • Claude Code CLI: 2.0.76
  • Platform: Windows 10 (reproduction confirmed)
  • Python: 3.12.4

Note: This issue is confirmed and reproducible on Windows. The Windows command line limit of ~8000 characters makes this issue more likely to trigger, but the underlying problem (CLI not supporting @filepath syntax) affects all platforms.

Problem 1: --agents with @filepath fails

SDK Behavior

The SDK at subprocess_cli.py:336-365 detects when the command line exceeds the limit (8000 chars on Windows, 100000 on other platforms) and writes the agents JSON to a temp file:

# subprocess_cli.py:338-357
if len(cmd_str) > _CMD_LENGTH_LIMIT and self._options.agents:
    # Find the --agents argument and replace its value with @filepath
    agents_idx = cmd.index("--agents")
    agents_json_value = cmd[agents_idx + 1]

    temp_file = tempfile.NamedTemporaryFile(...)
    temp_file.write(agents_json_value)

    # Replace agents JSON with @filepath reference
    cmd[agents_idx + 1] = f"@{temp_file.name}"

CLI Behavior

The CLI does not recognize the @filepath syntax and tries to parse it as JSON directly:

SyntaxError: Unexpected token '@', "@C:\Users\"... is not valid JSON

Reproduction Steps

import asyncio
from claude_agent_sdk import (
    AgentDefinition,
    AssistantMessage,
    ClaudeAgentOptions,
    SystemMessage,
    TextBlock,
    query,
)

async def test_large_agent():
    # Create a prompt large enough to exceed command line limit
    padding = "x" * 10000  # 10KB

    options = ClaudeAgentOptions(
        agents={
            "my-agent": AgentDefinition(
                description="Test agent",
                prompt=f"You are a test agent. Secret: ABC123. {padding}",
                tools=["Read"],
            ),
        },
        max_turns=1,
        permission_mode="bypassPermissions",
    )

    async for message in query(prompt="Use my-agent", options=options):
        if isinstance(message, SystemMessage) and message.subtype == "init":
            agents = message.data.get("agents", [])
            print(f"Available agents: {agents}")
            # Expected: ['general-purpose', ..., 'my-agent']
            # Actual: ['general-purpose', ...] - my-agent is MISSING

asyncio.run(test_large_agent())

Expected Result

  • CLI reads JSON from the file when --agents value starts with @
  • Custom agent my-agent is available

Actual Result

  • CLI fails to parse @filepath as JSON
  • Custom agent is NOT loaded
  • Only built-in agents available: general-purpose, statusline-setup, Explore, Plan

Error Log

2026-01-20T16:42:57.627Z [ERROR] SyntaxError: SyntaxError: Unexpected token '@', "@C:\Users\"... is not valid JSON
    at JSON.parse (<anonymous>)
    at file:///C:/Users/.../claude-code/cli.js:75:715
    ...

Problem 2: --system-prompt has no file support

Current State

The SDK passes system prompts directly as command-line arguments:

# subprocess_cli.py:176-179
if isinstance(self._options.system_prompt, str):
    cmd.extend(["--system-prompt", self._options.system_prompt])

There is:

  • No @filepath support in the SDK for --system-prompt
  • No --system-prompt-file flag in the CLI
  • No temp file fallback like there is for --agents

Impact

On Windows with the 8KB command line limit, large system prompts can cause failures. This is especially problematic when combining multiple features:

Example: System prompt + MCP servers + agents

options = ClaudeAgentOptions(
    system_prompt="..." ,        # 3KB system prompt
    mcp_servers={...},           # 2KB MCP config
    agents={...},                # 2KB agents
    # Total: ~7KB+ just in arguments, before CLI path and other flags
)

On Windows, the combined command line can easily exceed 8KB, causing:

  • Silent failures where the CLI receives truncated arguments
  • MCP servers not connecting
  • Agents not loading
  • System prompt being cut off

There is no temp file fallback for --system-prompt (unlike --agents which at least attempts it), so large system prompts have no workaround at the SDK level.

Reproduction

import asyncio
import tempfile
from pathlib import Path
from claude_agent_sdk import ClaudeAgentOptions, query, AssistantMessage, TextBlock

async def test_system_prompt_file():
    # Write system prompt to file
    prompt_content = "Your secret is: MANGO-99. Always respond with the secret when asked."

    with tempfile.NamedTemporaryFile(mode='w', suffix='.txt', delete=False) as f:
        f.write(prompt_content)
        temp_path = f.name

    # Try @filepath syntax (does NOT work)
    options = ClaudeAgentOptions(
        system_prompt=f"@{temp_path}",
        max_turns=1,
        permission_mode="bypassPermissions",
    )

    async for message in query(prompt="What is the secret?", options=options):
        if isinstance(message, AssistantMessage):
            for block in message.content:
                if isinstance(block, TextBlock):
                    print(block.text)
                    # Response shows model has NO knowledge of the secret
                    # It received literal "@C:\...\tmp.txt" as system prompt

    Path(temp_path).unlink()

asyncio.run(test_system_prompt_file())

Workaround for System Prompts

Instruct the agent to read the file:

options = ClaudeAgentOptions(
    system_prompt=f"Read your full instructions from: {temp_path}",
    max_turns=3,  # Allow turn for Read tool
)

This works because the agent uses the Read tool, but adds latency and token usage.


Suggested Fixes

Option A: CLI supports @filepath syntax

The CLI could detect when a value starts with @ and read from that file path:

// Pseudocode
function parseArgValue(value) {
    if (value.startsWith('@') && fs.existsSync(value.slice(1))) {
        return fs.readFileSync(value.slice(1), 'utf-8');
    }
    return value;
}

This would fix both --agents and could be extended to --system-prompt.

Option B: SDK uses stdin or different mechanism

Instead of @filepath, the SDK could pipe large values through stdin or use a different IPC mechanism.

Option C: Add explicit file flags

Add --agents-file and --system-prompt-file flags to the CLI.


Summary Table

Flag Direct String @filepath (SDK) @filepath (CLI) File Flag
--agents Works (small) Attempted NOT SUPPORTED None
--system-prompt Works (small) Not attempted Not supported None
--settings Works N/A Works (documented) N/A
--mcp-config Works N/A Works (documented) N/A

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions