feat: extend ToolSearch deferral to plugin skills

Resolved 💬 1 comment Opened Apr 8, 2026 by dnh33 Closed May 22, 2026

Summary

Plugin skills inject their name and description into an <available_skills> XML block in the system prompt on every turn. There is no deferral mechanism equivalent to what built-in tools received in v2.1.69 (#31002) or what MCP tools support via defer_loading: true. The result is a fixed per-turn token cost that scales linearly with the number of installed plugins regardless of whether any of those skills are relevant to the current task.

The Numbers

A user with 14 enabled plugins has approximately 152 skills and 35 agents listed every turn. At roughly 200 characters per entry, that is ~37,400 characters (~9,350 tokens) of skill descriptions baked into every system prompt. The SLASH_COMMAND_TOOL_CHAR_BUDGET caps injection at ~1% of the context window, which on a 200K-token model still permits 8,000–16,000 characters of skill descriptions per turn as a floor.

On Opus with the 5-hour rate limit, this overhead accumulates across every session. Users who install plugins for occasional use — image generation, marketing copy, PDF export — pay the full per-turn cost even when those skills will never be invoked.

What Already Works (And Doesn't Apply Here)

Built-in tools moved behind ToolSearch deferral in v2.1.69 (#31002). The partial reversion in v2.1.72 kept 9 core tools pre-loaded and deferred the rest — a "keep essential, defer the rest" pattern that is exactly what plugin skills need. MCP tools support defer_loading: true at the API level.

Plugin skills have no equivalent. Every enabled plugin, every turn.

Current Workarounds

None of the existing options are workable:

  • Disable plugins entirely — loses access to agents and bundled tools, not just skills
  • disable-model-invocation: true in SKILL.md — removes from context but makes it undiscoverable by Claude; manual-only invocation
  • Lower SLASH_COMMAND_TOOL_CHAR_BUDGET — truncates all descriptions, degrading Claude's ability to match any skill to any task
  • Permission deny rules — may still inject descriptions even when invocation is blocked

Proposed Solution

Extend ToolSearch deferral to plugin skills using the existing architecture.

  1. Register each plugin skill as a deferred entry in the ToolSearch index, keyed on name and description, rather than injecting into <available_skills> every turn
  2. Claude discovers skills via ToolSearch when it encounters a relevant task — same as deferred built-in tools
  3. The Skill tool itself remains pre-loaded. Only the per-skill description injection is deferred
  4. Skills with user-invocable: true continue to appear in the / command menu regardless of deferral state

| | Current | Proposed |
|---|---|---|
| Per-turn skill cost | O(n) — all installed skills | O(1) base + O(k) on query |
| Prompt cache efficiency | Low — prefix changes with skill count | Higher — stable prefix |
| Discoverability | Full descriptions always present | ToolSearch-indexed, on demand |

Related Issues

  • #31002 — Built-in tools deferred behind ToolSearch
  • #39686 — Cloud-synced skills silently consuming ~6K tokens with no opt-out
  • #14549 — marketplace.json duplication inflating skill count
  • #12836 — Original ToolSearch feature request
  • #32485 — Custom agents undiscoverable via ToolSearch

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗