[BUG] --disallowedTools and --tools cause silent 0-cost exit in pipe mode when combined with --mcp-config + large --append-system-prompt
Description
When using claude -p (pipe mode) with --disallowedTools or --tools combined with --mcp-config and a large --append-system-prompt (~18KB+), Claude Code exits immediately with code 0, produces no output, and consumes no tokens.
Removing the --disallowedTools/--tools flag while keeping all other flags unchanged produces the expected response.
Reproduction
# 1. Create a large system prompt file (~18KB)
cat > /tmp/large-prompt.txt << 'PROMPT'
# Vault Reference — Universal Architecture and Conventions
# ... (paste ~18KB of system prompt content) ...
PROMPT
LARGE_PROMPT=$(cat /tmp/large-prompt.txt)
# 2. Create a minimal MCP config with at least one server
cat > /tmp/mcp.json << 'MCP'
{
"mcpServers": {
"example": {
"command": "npx",
"args": ["-y", "@anthropic-ai/mcp-server-memory"]
}
}
}
MCP
# 3. This WORKS — produces output, consumes tokens:
claude -p \
--model claude-sonnet-4-6 \
--append-system-prompt "$LARGE_PROMPT" \
--output-format json \
--mcp-config /tmp/mcp.json \
--no-session-persistence \
-- "Say hello"
# 4. This SILENTLY EXITS — 0 exit code, no output, no tokens:
claude -p \
--model claude-sonnet-4-6 \
--append-system-prompt "$LARGE_PROMPT" \
--output-format json \
--mcp-config /tmp/mcp.json \
--disallowedTools "Edit,Write" \
--no-session-persistence \
-- "Say hello"
Key observation: The --disallowedTools flag uses variadic parsing (<tools...>). When combined with a large system prompt and MCP config, it appears to either consume the subsequent arguments or trigger an early exit path. Adding -- before the prompt (to separate variadic args from the positional prompt) resolves the argument parsing issue but the silent exit persists with MCP + large prompt.
Observed behaviour
- Exit code:
0 - stdout: empty
- stderr: empty
- API cost:
$0.00(no tokens consumed — the request never reaches the API) - No error message of any kind
Expected behaviour
Claude should process the prompt normally, applying the tool restrictions, and return a response. If the flag combination is unsupported, it should exit with a non-zero code and an error message.
Environment
- Claude Code version: 2.1.66
- OS: macOS 15.4 (Darwin 25.3.0), Apple Silicon
- Node: v22.x (Nix-managed)
- Shell: zsh
- Installation: Nix package (
pkgs.claude-code)
Workaround
Remove --disallowedTools / --tools flags. Operators run with default tool permissions. MCP tool access is still scoped via settings.json auto-approval list, but built-in tools (Bash, Edit, Write) cannot be restricted.
Additional context
This was discovered while building a generic operator dispatch system using claude -p with LaunchAgents. The intent was to sandbox operators by denying destructive tools (e.g., deny Write/Edit for a read-only operator, deny Bash for a vault-only operator). The combination of:
--mcp-config(4 MCP servers)--append-system-prompt(~18KB operator identity prompt)--disallowedTools(tool restriction)
reliably produces the silent exit. Removing any one of these flags changes the behaviour (e.g., without --mcp-config, --disallowedTools works fine with the large prompt).
Related: #25589 (--disallowedTools not affecting MCP tools — different bug, but same flag).
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗