claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

[BUG] Plugin cache causes 10x startup delay (inverted cache behavior)

Open chrisplough opened this issue 4 weeks ago • 0 comments

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Claude Code startup is 10x slower when plugin cache exists compared to when cache is empty. This is inverted cache behavior - the cache should speed up startup, not slow it down.

Condition Startup Time CPU Usage
Empty cache 4.4s 92%
Cache exists 41-46s 12%

The 12% CPU with 40+ second runtime indicates the process is waiting, not computing, likely blocking on sequential subprocess spawns for plugin validation/initialization.

Expected Behavior

  • Plugin cache should reduce startup time (cache hit = skip installation)
  • Plugin initialization should happen in parallel or lazily on first use
  • Cached plugins should validate quickly, not run full initialization

Actual Behavior

  • Plugin cache increases startup time by 10x
  • Appears to run sequential initialization for each cached plugin
  • Each plugin adds ~4 seconds to startup

Workaround

(Side note - I came to this after troubleshooting this issue for several hours, hoping to find a system-specific issue, rather than needing this workaround.)

Clear plugin cache before each session:

rm -rf ~/.claude/plugins/cache/*
rm -rf .claude/plugins/cache/*  # if using project-local plugins

This trades ~4s reinstallation for ~36s saved on validation.

What Should Happen?

Expected Behavior

  • Plugin cache should reduce startup time (cache hit = skip installation)
  • Plugin initialization should happen in parallel or lazily on first use
  • Cached plugins should validate quickly, not run full initialization

Related Issues

  • #7336 - Feature request for lazy loading MCP servers (related optimization)
  • #10997 - SessionStart hooks race condition with plugin loading
  • #13952 - LSP servers not loading due to plugin race condition

This issue differs: existing cache makes startup slower, not faster. The cache inversion suggests a validation loop that's more expensive than fresh installation.

Additional Context

  • Same behavior observed in both project-local and user-level plugin directories
  • Network trace shows normal activity before/after the gap - issue is subprocess-related, not network

Error Messages/Logs

## Environment

- **Claude Code version:** 2.0.75
- **Platform:** macOS Darwin 24.2.0 (Apple Silicon)
- **Node:** v24.12.0 (via mise) - also tested with v25.2.1
- **Shell:** zsh
- **Plugins installed:** 9 (from claude-plugins-official marketplace)
  - frontend-design, feature-dev, code-review, commit-commands, security-guidance
  - lua-lsp, pyright-lsp, rust-analyzer-lsp, typescript-lsp

---

### SIGINT Blocked During Startup

Claude Code cannot be interrupted with Ctrl+C during the delay:


~/projects ❯ date; time claude
Mon Dec 22 14:00:02 MST 2025
^C^C^C^C^C
[eventually starts after ~40s]


This indicates **synchronous subprocess calls** (`execSync`/`spawnSync`) rather than async. Synchronous calls block the Node.js event loop entirely, preventing signal handling until each subprocess completes.

### Filesystem Trace Evidence

Using `sudo fs_usage -w -f filesystem claude` during the 46s slow startup:


Run started:       13:29:13
First fs activity: 13:29:56  (43 seconds of ZERO activity)
Subprocess burst:  13:29:56-13:29:59 (all child process activity)
Run ended:         13:29:59


Multiple child processes spawned in final 3 seconds:
- claude.16349441, .16349442, .16349453, .16349462, .16349475, .16349476, .16349477

**43 seconds with no filesystem activity from parent process** = blocked waiting on external processes (npm/node for plugin initialization) that fs_usage doesn't trace by name.

### Network Trace Evidence

Using `sudo fs_usage -w -f network claude` during slow startup, a **37-second gap** appears in the trace:


13:32:16.186156  close  F=15
         [37 SECONDS OF SILENCE - NO FILESYSTEM OR NETWORK ACTIVITY]
13:32:53.208083  socketpair


This gap suggests Claude spawns child processes (npm/node for plugin initialization) that `fs_usage` doesn't trace because it's filtering by the parent PID.

With 9 plugins: 37s ÷ 9 ≈ **4s per plugin** - matching the "fast" startup time when cache is empty and plugins reinstall.

Steps to Reproduce

1. Clear plugin cache

rm -rf ~/projects/pai/.claude/plugins/cache/*

2. First run - fast (rebuilds cache)

time claude

Result: ~4.4s, 92% CPU

3. Exit and run again - slow (uses cache)

time claude

Result: ~41s, 12% CPU

4. Clear cache again

rm -rf ~/projects/pai/.claude/plugins/cache/*

5. Run again - fast

time claude

Result: ~4.7s, 89% CPU

Claude Model

Not sure / Multiple models

Is this a regression?

I don't know

Last Working Version

No response

Claude Code Version

2.0.75

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Other

Additional Information

No response

chrisplough avatar Dec 22 '25 21:12 chrisplough