From cfa4922cc929da53f97b79ee5d431422180d6f11 Mon Sep 17 00:00:00 2001 From: Its My Work Date: Mon, 14 Sep 2026 22:40:42 +0000 Subject: [PATCH] fix(cli): use --tools to actually shrink the built-in tool schema set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --allowedTools is a permission filter on top of whatever tools the CLI makes available by default — it does not reduce what gets sent to and cached by the API. Every caller here passes a short, fixed built-in tool list (9 or fewer names), but the CLI's real default built-in set is larger, so its full schemas were generated and billed on every session's first message regardless of this restriction. Measured against the live app (real API calls, not an estimate): ~18,562 tokens — current behavior (--allowedTools only) ~6,961 tokens — same 9 tool names via --tools instead ~63% reduction, no functional change: MCP tools (mcp__server__tool) aren't part of "the built-in set" --tools restricts, so ask_user/ notify_user/set_ui_state/check_user_messages stay governed by mcpServers + allowedTools exactly as before — verified this separately by keeping --tools "" while still routing an MCP tool through allowedTools successfully. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_011E2bJQ2sL9LgEWosjvydTR --- claude-cli.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/claude-cli.js b/claude-cli.js index b199200..0c823af 100644 --- a/claude-cli.js +++ b/claude-cli.js @@ -266,7 +266,22 @@ class ClaudeCLI { // --tools: control which built-in tools are available. // "" disables all tools, "default" enables all, or specify names (e.g. "Bash,Edit,Read"). - if (typeof tools === 'string') args.push('--tools', tools); + if (typeof tools === 'string') { + args.push('--tools', tools); + } else if (allowedTools?.length) { + // --allowedTools alone is a permission FILTER on top of whatever tools the + // CLI makes available by default — it does not shrink what gets sent to the + // API. Every caller here passes a short, fixed built-in tool list (9 or + // fewer), but the CLI's actual default built-in set is bigger, so its full + // schemas were being generated and cached on every session regardless of + // this list (measured: ~18.5k tokens default vs ~7k restricted via --tools + // for the same 9 names — real API usage, not a guess). MCP tools + // (mcp__server__tool) aren't part of "the built-in set" --tools restricts; + // they stay governed by mcpServers + allowedTools alone, so filtering them + // out here doesn't touch ask_user/notify_user/etc. availability. + const builtins = allowedTools.filter(t => !/^mcp__/.test(t)); + if (builtins.length) args.push('--tools', builtins.join(',')); + } // allowedTools: pass each tool as separate arg (variadic) if (allowedTools?.length) args.push('--allowedTools', ...allowedTools);