# Claude Code tool & context audit **Date:** 2026-06-30 **Question:** Are too many built-in CC tools loaded into context, slowing sessions and hurting focus? Which can be excluded globally vs. situationally? **Method:** Mechanically parsed every tool-call (`tool_use`) across **224 main sessions + 1,946 subagent transcripts = 2,170 transcripts** in `~/.claude/projects/`, cross-referenced against the full tools reference (https://code.claude.com/docs/en/tools-reference.md), and measured the actual bytes loaded into one representative session's startup context. --- ## TL;DR — the hypothesis is mostly outdated Excluding **built-in tools** used to meaningfully shrink the prompt. It no longer does, because Claude Code now **defers** rarely-used tool schemas (tool search): they load on demand via `ToolSearch`, not at startup. - Total *static* startup context in a typical session here ≈ **6,300 tokens**. - Built-in tool schemas are a small slice of that; **MCP cost = 0** (no MCP servers configured). **Skills (50) ≈ 3,700 tok** are the single largest contributor. - Of **24 built-in tools never used in 2,170 transcripts**, only **one** (`Workflow`) is both always-loaded *and* unused. The other 23 are already deferred, platform- impossible, or trivially small. So: a confident global *tool* exclusion list exists, but its payoff is small. The real levers for "feels slow / unfocused" are elsewhere (see §5). > ⚠️ Honest caveat: trimming context lowers prefill latency and cost and may sharpen > focus, but it does **not** change Opus's per-token generation speed. Opus is simply > slower to generate than Sonnet/Haiku; no amount of tool pruning fixes that. --- ## 1. What tools actually get used (2,170 transcripts) | Tool | Calls | Transcripts using it | |---|---:|---:| | Bash | 9,168 | 1,248 | | Read | 5,955 | 1,185 | | Edit | 1,983 | 501 | | Agent | 1,948 | 541 | | Write | 981 | 382 | | WebFetch | 288 | 72 | | ToolSearch | 169 | 139 | | WebSearch | 124 | 36 | | AskUserQuestion | 108 | 70 | | Skill | 104 | 84 | | TaskUpdate / TaskCreate | 54 / 31 | 10 / 7 | | SendMessage | 40 | 27 | | Monitor | 21 | 12 | | TaskStop / ScheduleWakeup | 8 / 4 | 5 / 3 | | RemoteTrigger / ReportFindings | 1 / 1 | 1 / 1 | **Never used anywhere (0 calls):** `Artifact`, `CronCreate/Delete/List`, `EnterPlanMode/ExitPlanMode`, `EnterWorktree/ExitWorktree`, `Glob`, `Grep`, `ListMcpResourcesTool`, `LSP`, `NotebookEdit`, `PowerShell`, `PushNotification`, `ReadMcpResourceTool`, `SendUserFile`, `ShareOnboardingGuide`, `TaskGet/TaskList/TaskOutput`, `TodoWrite`, `WaitForMcpServers`, `Workflow`. > Note `Grep`/`Glob` show **0** — search runs through `Bash` (ripgrep/find directly, > reinforced by the RTK proxy). They are still worth keeping (see §4). --- ## 2. The decisive cross-reference: never-used ∩ actually-loaded The "never used" list conflates three very different things. Only the first bucket gives back real context when excluded. | Bucket | Tools | Exclusion payoff | |---|---|---| | **Always-loaded & unused** | `Workflow` | **Real** — large schema | | **Already deferred** (loaded on demand, not at startup) | `CronCreate/Delete/List`, `EnterPlanMode/ExitPlanMode`, `EnterWorktree/ExitWorktree`, `LSP`, `NotebookEdit`, `PushNotification`, `TaskGet/List/Output` | **~0** — not in the prompt anyway | | **Platform/plan-impossible or not loaded here** | `PowerShell` (Linux), `Artifact`/`ShareOnboardingGuide` (need Team/Ent.), `SendUserFile`/`PushNotification` (need Remote Control), `TodoWrite` (disabled by default), `WaitForMcpServers` (only when tool-search is OFF), `Glob`/`Grep`, MCP-resource tools | **Cosmetic** — either absent or trivially small | **This is why manual exclusion mattered more in the past:** tool-search deferral now does the trimming automatically. --- ## 3. Where the startup context actually goes (~6,300 tok measured) | Contributor | Est. tokens | # items | |---|---:|---:| | **Skills** (name + description) | ~3,700 | 50 | | **Subagent types** | ~917 | 18 | | CLAUDE.md (project) | ~842 | 1 | | MEMORY.md auto-index | ~427 | 1 | | RTK.md | ~241 | 1 | | CLAUDE.md (global) | ~148 | 1 | | **MCP tool schemas** | **0** | 0 servers | | **Total** | **~6,300** | | Skills + agents = ~74% of static context. Heaviest single items: the built-in `claude-api` skill (~269 tok), personal `the-humanizer` (~239), `impeccable` (~226), `memsearch:memory-recall` (~185). --- ## 4. Recommendation A — global tool exclusions (small but safe) Add to `~/.claude/settings.json` `permissions.deny`. The mechanism: a denied tool is removed from the advertised set (its schema isn't loaded), per the tools reference ("to disable a tool entirely, add its name to the deny array"). Verify by checking the session token count before/after if you want proof. ```jsonc { "permissions": { "deny": [ "Workflow", // 0/2170 uses; largest always-loaded built-in schema. // KEEP it ONLY if you use /workflows or "ultracode". "PowerShell", // Linux host — never available. Cosmetic. "Artifact", // needs Team/Enterprise plan. Cosmetic. "ShareOnboardingGuide" // paid team feature. Cosmetic. ] } } ``` - **`Workflow` is the only entry with real payoff.** It is the multi-agent orchestration tool (the big JS-script one) — *not* `Agent`. You use `Agent` constantly (1,948 calls) and `Workflow` never. Keep `Agent`; drop `Workflow` unless/until you adopt `/workflows`. - **Do NOT deny** `Glob`/`Grep` (tiny; the sanctioned search path — denying pushes everything to `Bash grep`/`find`, which can add permission prompts), anything **deferred** (no savings), or plan-mode/worktree/Task tools (deferred *and* UI-driven — denying `ExitPlanMode` would break Shift-Tab plan mode). Net context saved: roughly the `Workflow` schema. Honest, but modest. --- ## 5. Recommendation B — the real lever: situational plugins/skills Skills/agents (~4,600 tok) dwarf the built-in-tool headroom, and they load *every* session regardless of relevance. These are controlled per-machine via `enabledPlugins` in `~/.claude/settings.json` (not easily per-project), so the practical move is toggling plugins by what you're doing. Currently enabled: `superpowers` (already disabled ✓), `ruby-lsp`, `perspectives`, `git-context`, `invoice-ninja`, `memory`, `memsearch`, `doc-hygiene`, `codex`. | Plugin / skill group | Relevant to | Drop when not… | |---|---|---| | `codex:*` (5 skills + agent) | coding handoffs to Codex | …coding | | `ruby-lsp` | Ruby projects | …in a Ruby repo | | `perspectives:*` (9 agents) | design/plan critique | …planning/designing | | `invoice-ninja` | freelance billing | …doing client billing | | `deep-research`, web tools | research | …researching | | personal writing/UI: `the-humanizer`, `impeccable`, `edit-article`, `prototype` | content/frontend | …writing or building UI | | `doc-hygiene:*` | docs repos | …maintaining docs | | `memory:*` + `memsearch:*` | cross-session recall | rarely — but see below | **Suggested situational profiles** (toggle `enabledPlugins`): - **Coding repo:** keep `codex`, `ruby-lsp` (if Ruby), `git-context`. Drop `invoice-ninja`, writing/UI skills, `deep-research`, `perspectives`. - **Freelance / PM / client:** keep `invoice-ninja`, `git-context`. Drop `codex`, `ruby-lsp`, `perspectives`, coding skills (`tdd`/`diagnose`/`run`/`verify`). - **Research / writing:** keep `deep-research`, writing skills. Drop `codex`, `ruby-lsp`, `invoice-ninja`. - **Infra / sysadmin (this repo):** Bash/Read/Edit-heavy. Drop writing/UI, `invoice-ninja`, `codex`, coding frameworks; keep `doc-hygiene`, `git-context`. > Reality check: even the full ~6.3k static context is small next to a working > session that fills 50k–150k+ tokens. Trimming skills is good hygiene and helps > focus, but it is not where most of a slow session's time goes. --- ## 6. What is probably actually slowing sessions Ranked by likely impact, from the data: 1. **Opus generation speed.** Inherent; switch to Sonnet/Haiku for mechanical work, or use `/fast` (faster Opus output) for interactive coding. 2. **Heavy `Agent` delegation.** 67% of sessions spawn subagents; 541 transcripts used `Agent`. Each subagent is a fresh context with its own prefill + sequential wall-clock wait. Great for big fan-out; pure latency for small lookups you could do inline. 3. **Per-prompt / per-tool hooks.** The `memory` plugin registers all 5 hook types, incl. **PostToolUse (runs after every tool call)** and SessionStart/UserPromptSubmit (the large memory dump at session start). `memsearch` adds more. This is a per-operation tax that tool-count pruning won't touch — worth timing/disabling to test. **Most promising thing to measure next.** 4. **Long sessions** → context summarization passes. Use `/clear` between unrelated tasks rather than carrying one giant session. 5. Static tool/skill context (this audit) — real but the **smallest** of these. --- ## Appendix — four representative sessions (loaded vs. used) 1. **Coding** (`llf-schema/19320d96`) — implement an OpenSpec change. 191 calls, only **Edit/Read/Write/Bash**. No web, no `Agent`, no skills. Pure local code loop. 2. **Infra, wide** (`proxmox-hermes-01/c24faa0a`) — plan a Proxmox agent setup. Used nearly the whole belt: Bash/Agent/WebFetch/WebSearch/Read/Edit/Write/ AskUserQuestion/Skill(`git-context:repo-init`). The legit case for keeping web tools loaded. 3. **Infra, ops** (`systems-admin/ffed234f`) — "how did the backup do this week?" 50 calls, only **Bash/Read/Edit/Write**. Textbook shell-only profile. 4. **PM / orchestration** (`ovh-prod-01/991913d9`) — decide next server-consolidation phase. Lead agent used only **Agent + AskUserQuestion**; 360+ tool calls happened in 40 subagents. Never touched a file or shell itself. Three of four would have been unaffected by stripping every web tool, every skill, and (for #1/#3) all delegation tooling. --- ## Addendum (2026-06-30) — follow-up: skills, hooks, and orchestration ### Skill loading — there IS a native lever (no "dispatcher" needed) Per the docs: a skill's **body** loads only on invocation ("costs almost nothing until you need it"); only **name + description** load at startup, and that listing is **budget-capped** (`skillListingBudgetFraction`, ~1% of context; `skillListingMaxDescChars` default 1,536/skill). There is **no** skill-level `ToolSearch` equivalent. To reduce always-loaded skill weight, use **`skillOverrides`** in settings rather than a community dispatcher skill: - `"name-only"` — keep the skill available but drop its description from context. - `"off"` — hide it entirely. Plus `enabledPlugins`, `disableBundledSkills: true`. The dispatcher/index pattern is **not** officially recommended — the budget + `skillOverrides` already do it. ### Hooks are synchronous but cheap (measured on this machine) Hooks block the turn until exit (up to `timeout`); `"async": true` makes one fire-and-forget. The `memory` plugin's hooks are synchronous but fast: `post_tool_use_write` ~38 ms (Write|Edit only, early-exits off-vault), `session_context` ~33 ms/prompt (injects ~0 tokens normally), `rtk hook` ~24 ms/Bash. Negligible vs. multi-second model turns. **Not a latency source.** The big memory dump is SessionStart-only (once). ### Orchestration audit — subagent model mismatch (1,962 transcripts) Model is recorded per subagent transcript. Distribution: **Sonnet 36.7% · Haiku 36.5% · Opus 26.6%**. By work profile: | Subagent model | n | % that did only file-edit/shell work | |---|---:|---:| | Opus | 521 | 53% (+38% spawned their own subagents) | | Sonnet | 720 | 64% | | Haiku | 716 | 83% (well-matched) | **Finding:** 27% of subagents run on **Opus**, most doing mechanical edits. Root cause: when an `Agent` spawn omits `model`, the subagent **inherits the parent model (Opus)** — so the CLAUDE.md routing table is advisory and leaks. **Subagent model resolution order** (docs): `CLAUDE_CODE_SUBAGENT_MODEL` env → per-invocation `model` param → subagent frontmatter `model:` → inherited main model. **Enforcement fix:** set **`CLAUDE_CODE_SUBAGENT_MODEL=haiku`** (or `sonnet`) so subagents default cheap instead of inheriting Opus; pin per-type `model:` frontmatter for specialized agents; escalate by explicit criteria only. **Instruction tuning (pilot on one project first):** 1. Drop "no minimum complexity threshold" — direct-operate trivial single-file ops; delegate only when parallelizable, large, or context-heavy. Mandatory delegation of one-line edits is a net latency *loss*. 2. Make routing enforced, not advisory (env var above + "always pass model on spawn"). 3. Relax "never read before delegating" — allow a cheap orienting read when paths/ structure are uncertain, to avoid blind-spec retry loops.